Как сделать недействительным сеанс C # WCF, если вход неверный - PullRequest
2 голосов
/ 20 октября 2010

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

Ответы [ 2 ]

0 голосов
/ 27 мая 2011

Сделайте что-то вроде этого:

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();
}

Это приведет к сбою канала, и клиенту придется заново установить сеанс

0 голосов
/ 20 октября 2010

Создание исключения - безусловно, самый простой вариант, потому что WCF обеспечивает невозможность повторного использования сеанса.Из того, что я понял, что вы хотели бы, чтобы сторонний компонент выполнял, довольно близко подходит к этой функциональности.Но вместо того, чтобы заставлять клиента снова вызывать IsInitialized, вы заставляете клиента создавать новое соединение.Для меня это выглядит очень маленькой разницей.

Альтернативой может быть приватная переменная bool _authorised и проверка этой переменной при каждом вызове метода.

...