Я пишу удаленный сервис для приложения, использующего WCF, в котором информация для входа хранится в базе данных. Услуга требует установления сеанса посредством входа в систему или вызова создания учетной записи. ASP не задействован.
Теперь, когда клиент начинает сеанс, вызывая открытый метод IsInitiating , я проверяю предоставленные данные учетной записи и информацию в базе данных, и, если она неверна, я хочу аннулировать этот сеанс и вынудить клиента начать снова с вызова метода IsInitiating .
Глядя на некоторые другие вопросы, я нашел плюсы и минусы для двух способов сделать сеанс недействительным. Один делает это трудным путем, бросая FaultException; другой с более мягкими манерами, сохраняя принятые идентификаторы сессии.
Теперь первый, хотя и добивается того, чего я желаю, слишком агрессивен, учитывая, что неправильные входы в систему являются частью нормального потока приложения. Второй, с другой стороны, позволяет клиенту продолжать вызывать неинициирующие методы, даже если они будут отклонены, и в то же время влечет за собой значительные накладные расходы на код из-за дополнительных требований безопасности потока.
Итак, вопрос: существует ли третий путь, который позволяет службе сделать недействительной инициализацию сеанса и передать ее клиенту, поэтому он вынужден сделать новый 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;
}
}