我正在使用 WCF 为应用程序编写远程服务,其中登录信息保存在数据库中。该服务需要通过登录或帐户创建调用建立会话。不涉及 ASP。
现在,当客户端通过调用公开的IsInitiating方法启动会话时,我会根据数据库上的信息检查提供的帐户数据,如果不正确,我想使该会话无效并强制客户端重新启动调用IsInitiating方法。
查看其他一些 问题,我发现了两种使会话无效的方法的优缺点。一种方法是通过抛出一个 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;
}
}