Нестандартный элемент верификации WCF: Как инициализировать “Пользовательский” объект от нестандартного элемента верификации

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

Этот класс происходит из Системы. IdentityModel. Селекторы. UserNamePasswordValidator и Проверение () метод возвращаются пусто.

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

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

Обновление: Это - то, как я работал вокруг этого. Я кэширую Пользовательский объект во время блока проверки допустимости, затем получаю доступ к нему позже на шаге 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;
  }
5
задан John Saunders 20 February 2010 в 03:58
поделиться

2 ответа

Я не 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

5
ответ дан 14 December 2019 в 13:34
поделиться

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

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

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

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

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

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

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

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

(извините, что не могу избавиться от этой плохой HTML-эскейпинга)

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

    public bool Evaluate(EvaluationContext evaluationContext, ref object state)
    {
     IIdentity identity = GetClientIdentity(evaluationContext);
     if (identity == null)
     throw new Exception();
    
     // Это мои пользовательские классы Identity и Principal
     Identity customIdentity = new Identity();
     Principal customPrincipal = new Principal(customIdentity);
     // заполняем идентификатор и принципала по мере необходимости
     evaluationContext.Properties["Principal"] = customPrincipal;
     return true;
     }
    

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

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

Стив

1
ответ дан 14 December 2019 в 13:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: