2


2

ログインが正しくない場合にC#WCFセッションを無効にする方法

ログイン情報がデータベースに保持されるWCFを使用して、アプリケーションのリモートサービスを作成しています。 このサービスでは、ログインまたはアカウント作成の呼び出しによるセッションの確立が必要です。 関連するASPはありません。

ここで、クライアントが公開された_IsInitiating_メソッドを呼び出してセッションを開始すると、提供されたアカウントデータをデータベースの情報と照合し、それが正しくない場合、そのセッションを無効にし、クライアントを強制的に再起動します_IsInitiating_メソッドの呼び出し。

someを見るhttps://stackoverflow.com/questions/100053/wcf-overhead-of-throwing-faultexceptions-within-your-service [その他]質問、セッションを無効にする2つの方法の長所と短所を見つけました。 FaultExceptionをスローすることにより、困難な方法を実行します。もう1つはマナーがよりソフトで、受け入れられたセッションIDを保存します。

さて、最初の1つは、私が望むものを達成しましたが、アプリケーションの通常のフローの一部である不正なログインを考えると、あまりにも攻撃的です。 一方、2番目の方法では、クライアントは拒否されますが、開始されていないメソッドの呼び出しを続けることができます。また、追加のスレッドセーフティ要件により、サービスでかなりのコードオーバーヘッドが発生します。

だから、質問:サービスがセッションの初期化を無効にしてクライアントに通信できるようにする3番目のパスがあり、新しい_IsInitiating_呼び出しを行うことを強制されますか?

私が持っているコードの縮小版:

[DataContractAttribute]
public class AccountLoginFault
{
    public AccountLoginFault (string message)
    {
        this.Message = message;
    }

    [DataMemberAttribute]
    public string Message { get; set; }
}

[ServiceContract (SessionMode = SessionMode.Required)]
public interface IAccountService
{
    [OperationContract (
        IsInitiating = true)]
    [FaultContractAttribute (
        typeof (AccountLoginFault),
        ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    bool Login (AccountData account, out string message);
}

[ServiceBehavior (
    ConcurrencyMode = ConcurrencyMode.Single,
    InstanceContextMode = InstanceContextMode.PerSession)]
public class AccountService : IAccountService
{
    public bool Login (AccountData account, out string message)
    {
        UserManager userdb = ChessServerDB.UserManager;
        bool result = false;
        message = String.Empty;

        UserData userData = userdb.GetUserData (account.Name);

        if (userData.Name.Equals (account.Name)
            && userData.Password.Equals (account.Password))
        {
            // Option one
            // Get lock
            // this.AcceptedSessions.Add (session.ID);
            // Release lock

            result = true;
        } else
        {
            result = false;

            // Option two
            // Do something with session context to mark it as not properly initialized.
            // message = "Incorrect account name or password. Account provided was " + account.Name;

            // Option three
            throw new FaultException (
                new AccountLoginFault (
                    "Incorrect account name or password. Account provided was " + account.Name));
        }

        return result;
    }
}

2 Answer


0


WCFはセッションを再利用できないように強制しているため、例外をスローするのが最も簡単なオプションです。 私が収集したものから、サードパーティのコンポーネントで達成したいことは、この機能に非常に近いものです。 ただし、クライアントにIsInitializedを再度呼び出すように強制する代わりに、クライアントに新しい接続の作成を強制します。 これは私にとって非常に小さな違いのように見えます。

別の方法として、プライベート変数bool _authorisedを用意し、メソッド呼び出しのたびにこの変数をチェックすることもできます。


0


このようなことをしなさい:

public ConnectResponseDTO Connect(ConnectRequestDTO request) {
    ...
    if(LoginFailed)
        OperationContext.Current.OperationCompleted += FaultSession;
}

private void FaultSession(object sender, EventArgs e) {
    var context = (OperationContext) sender;
    context.Channel.Abort();
}

これによりチャネルに障害が発生し、クライアントはセッションを再確立する必要があります。