Я пишу удаленную службу для приложения, использующего 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;
}
}