Пользовательский валидатор WCF: как инициализировать объект «Пользователь» из пользовательского валидатора - PullRequest
5 голосов
/ 19 февраля 2010

У меня есть рабочий пользовательский UserNamePasswordValidator, который вызывает мою базу данных Oracle.

Этот класс является производным от System.IdentityModel.Selectors.UserNamePasswordValidator, а метод Validate () возвращает void.

Я загружаю свой объект User из базы данных, и после того, как пароль проверен, я хочу спрятать свой объект "User", чтобы служба могла получить к нему доступ при работе. В ASP.NET / Java Land я бы спрятал его в сеанс или, возможно, мой общий класс Controller. Как мне сделать это из валидатора в WCF?

Или, другими словами, какова лучшая практика в земле WCF для установки пользовательского объекта домена пользователя для службы.

Обновление: так я обошёл это. Я кэширую объект User во время валидатора, а затем обращаюсь к нему позже на этапе AuthorizatinPolicy.

  // this gets called after the custom authentication step where we loaded the User
  public bool Evaluate(EvaluationContext evaluationContext, ref object state)
  {
     // get the authenticated client identity
     IIdentity client = GetClientIdentity(evaluationContext);

     User user;
     OraclePasswordValidator.users.TryGetValue(client.Name, out user);
     if(user != null) {
        // set the custom principal
        evaluationContext.Properties["Principal"] = user;
        return true;
     }

     return false;
  }

Ответы [ 2 ]

5 голосов
/ 10 марта 2010

Я не эксперт WCF, но из того, что я прочитал и реализовал до сих пор, «правильный» способ сделать это - использовать Validator для аутентификации пользователя, а затем реализовать IAuthorizationPolicy, чтобы выполнить фактическую авторизацию . Таким образом, в политике авторизации вы будете устанавливать свой собственный принципал в текущем потоке.

Чтобы иметь возможность пересылать информацию из проверки имени пользователя / пароля, вы можете реализовать аутентификатор токена безопасности, который наследуется от UserNameSecurityTokenAuthenticator. SecurityTokenAuthenticator сначала вызовет валидатор, и, если проверка прошла успешно, он может добавить свою пользовательскую политику авторизации и отправить информацию о пользователе в политику через конструктор. Что-то длинное в этом:

public class CustomUsernameSecurityTokenAuthenticator : UserNameSecurityTokenAuthenticator
{
    protected override bool CanValidateTokenCore(System.IdentityModel.Tokens.SecurityToken token)
    {
        return (token is UserNameSecurityToken);
    }

    protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateTokenCore(SecurityToken token)
    {
        var authorizationPolicies = new List<IAuthorizationPolicy>();

        try
        {
            var userNameToken = token as UserNameSecurityToken;
            new CustomUserNameValidator().Validate(userNameToken.UserName, userNameToken.Password);

            var claims = new DefaultClaimSet(ClaimSet.System, new Claim(ClaimTypes.Name, userNameToken.UserName, Rights.PossessProperty));

            authorizationPolicies.Add(new CustomAuthorizationPolicy(claims));
        }
        catch (Exception)
        {
            authorizationPolicies.Add(new InvalidAuthorizationPolicy());
            throw;
        }
        return authorizationPolicies.AsReadOnly();
    }
}

Здесь есть статья, которая описывает немного больше о вовлеченных классах; http://blogs.msdn.com/card/archive/2007/10/04/how-identity-providers-can-show-custom-error-messages-in-cardspace.aspx

1 голос
/ 20 февраля 2010

У меня точно такая же проблема.

Я использую API для соединения с моей базой данных Oracle, и я "проверяю" данные для входа, открывая соединение.

Затем я хочучтобы хранить это соединение где-то (достаточно просто, я создам пул соединений для всех разных пользователей), но также создаю пользовательскую личность и принципала, представляющих этого пользователя, так что, как только он попадет в мою пользовательскую IAuthorizationPolicy, ему не нужноперезагрузите эту информацию.

Я много занимался поиском и ничего не нашел, поэтому я планирую сделать это:

  1. Проверить данные для входа в систему в пользовательском UserNamePasswordValidator, открыв APIconnection.

  2. Хранить открытое соединение в пуле соединений под именем пользователя.

  3. Когда вызывается мой пользовательский IAuthorizationPolicy.Evaluate (), я будупосмотрите на предоставленную общую идентификацию:

    IIdentity GetClientIdentity(EvaluationContext evaluationContext)
    {
        object obj;
        if (!evaluationContext.Properties.TryGetValue("Identities", out obj))
            throw new Exception("No Identity found");
    
           IList<IIdentity> identities = obj as IList<IIdentity>;
           if (identities == null || identities.Count <= 0)
              throw new Exception("No Identity found");
    
           return identities[0];
       }
    

(извините, я не могу избавиться от этого плохого выхода из HTML)

Затем я получаю соединение из пула на основе IIdentity.Name, использую это соединение для загрузки пользовательских данных из базы данных и сохраняю их в пользовательских идентификаторах и принципалах, которые я установил в EvaluationContext:

public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
    IIdentity identity = GetClientIdentity(evaluationContext);
    if (identity == null)
        throw new Exception();

        // These are my custom Identity and Principal classes
        Identity customIdentity = new Identity();
        Principal customPrincipal = new Principal(customIdentity);
        // populate identity and principal as required
        evaluationContext.Properties["Principal"] = customPrincipal;
        return true;
    }

Тогда я должен иметь доступ к своей пользовательской идентификационной информации и принципалу всякий раз, когда мне это нужно, с помощью System.Threading.Thread.CurrentPrincipal или CurrentIdentity.

Надеюсьпомогает каким-то образом;Я не уверен, что это лучший способ сделать это, но это лучшее, что я придумал до сих пор ...

Стив

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...