如果登录不正确,如何使C#WCF会话无效

时间:2010-10-20 13:23:24

标签: c# wcf service login faultexception

我正在为使用WCF的应用程序编写远程服务,其中登录信息保存在数据库中。该服务需要通过登录或帐户创建调用建立会话。没有涉及ASP。

现在,当客户端通过调用公开的 IsInitiating 方法启动会话时,我会根据数据库中的信息检查提供的帐户数据,如果不正确,我想使其无效会话并通过调用 IsInitiating 方法强制客户端重新启动。

查看some other个问题,我找到了两种使会话无效的方法的优缺点。通过抛出FaultException,人们就这么做了。另一种方式更柔和,存储已接受的会话ID。

现在,第一个虽然实现了我想要的,但是过于激进,因为错误的登录是应用程序正常流程的一部分。另一方面,第二个允许客户端继续调用非启动方法,尽管它们将被拒绝,同时由于增加的线程安全要求而导致服务上相当大的代码开销。

所以,问题是:是否有第三条路径允许服务使会话初始化无效并将其传递给客户端,因此它被迫进行新的 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<AccountLoginFault> (
                new AccountLoginFault (
                    "Incorrect account name or password. Account provided was " + account.Name));
        }

        return result;
    }
}

2 个答案:

答案 0 :(得分:0)

抛出异常是迄今为止最简单的选项,因为WCF强制执行会话无法重用。从我收集的内容来看,您希望第三方组件实现的功能与此功能非常接近。但是,不是强制客户端再次调用IsInitialized,而是强制客户端创建新连接。这对我来说似乎是一个非常小的差异。

另一种方法是使用私有变量bool _authorised并在每次方法调用时检查此变量。

答案 1 :(得分: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();
}

这会使频道出错,客户端将会重新建立会话。