2

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

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

他のいくつか の質問を見て、セッションを無効にする 2 つの方法の長所と短所を見つけました。これは、FaultException をスローするという難しい方法で行います。もう 1 つは受け入れられたセッション ID を保存する、よりソフトなマナーです。

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

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

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

[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<AccountLoginFault> (
                new AccountLoginFault (
                    "Incorrect account name or password. Account provided was " + account.Name));
        }

        return result;
    }
}
4

2 に答える 2

0

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

別の方法は、プライベート変数 bool _authorized を持ち、メソッド呼び出しごとにこの変数をチェックすることです。

于 2010-10-20T13:27:47.287 に答える
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();
}

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

于 2011-05-27T03:00:09.430 に答える