Может ли пользовательский UserNamePasswordValidator использоваться в качестве поставщика ролей? - PullRequest
3 голосов
/ 24 августа 2010

В связи с этим вопросом , у меня есть пользовательский UserNamePasswordValidator, который входит в наш внутренний API. В рамках этого входа в систему я могу обнаружить роли пользователя в нашей системе.

Я хотел бы позже использовать их в требованиях PrincipalPermissionAttribute к методам обслуживания, например ::100100

[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role = "System Administrator")]
public string HelloWorld()
{ /* ... */ }

Ответы [ 2 ]

6 голосов
/ 15 апреля 2011

Расширить ответ Ладислава:

Нет.Пользовательский UserNamePasswordValidator нельзя использовать в качестве поставщика ролей.UserNamePasswordValidator запускается в отдельном контексте (или потоке или чем-то) от OperationContext, с которым вы хотите связываться.

Вместо этого вам нужно реализовать пользовательскую авторизацию.Я нашел эту страницу наиболее полезной для этого.Предупреждение: прежде чем вы перейдете к интересным битам, вам предстоит многое сделать.

По сути, вы начинаете с класса ServiceCredentials, зарегистрированного в App.config, как показано ниже:1013 * Свяжите поведение с вашим сервисом.

Переопределите ServiceCredentials.CreateSecurityTokenManager, чтобы получить MySecurityTokenManager, полученное из ServiceCredentialsSecurityTokenManager.На этом переопределите CreateSecurityTokenAuthenticator, возвращая MySecurityTokenAuthenticator.Это следует из CustomUserNameSecurityTokenAuthenticator.В этом переопределите ValidateUserNamePasswordCore.Вызовите базовый класс, который вернет список политик авторизации.

К этому списку добавьте новый: MyAuthorizationPolicy, который реализует IAuthorizationPolicy.При этом вам просто (хах) нужно сделать следующее:

public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
    IList<IIdentity> identities = GetIdentities(evaluationContext);

    // Find the GenericIdentity with our user-name in it.
    IIdentity currentIdentity = identities.SingleOrDefault(
        i => i is GenericIdentity &&
        StringComparer.OrdinalIgnoreCase.Equals(i.Name, UserName));
    if (currentIdentity == null)
        throw new InvalidOperationException("No Identity found");

    // Replace the GenericIdentity with a new one.
    identities.Remove(currentIdentity);
    var newIdentity =
        new GenericIdentity(_userName, currentIdentity.AuthenticationType);
    identities.Add(newIdentity);

    // This makes it available as
    // ServiceSecurityContext.Current.PrimaryIdentity later.
    evaluationContext.Properties["PrimaryIdentity"] = newIdentity;

    // This makes it available as Thread.CurrentPrincipal.
    IPrincipal newPrincipal = new GenericPrincipal(newIdentity, _roles);
    evaluationContext.Properties["Principal"] = newPrincipal;

    return true;
}

private static IList<IIdentity> GetIdentities(
    EvaluationContext evaluationContext)
{
    object identitiesProperty;
    if (!evaluationContext.Properties.TryGetValue(
        "Identities", out identitiesProperty))
    throw new InvalidOperationException("No Identity found");

    var identities = identitiesProperty as IList<IIdentity>;
    if (identities == null)
        throw new InvalidOperationException("No Identity found");
    return identities;
}

И затем, выполнив этот лот, вы можете пометить свои операции с помощью PrincipalPermission:

[PrincipalPermission(SecurityAction.Demand, Role = "Editor")]
2 голосов
/ 24 августа 2010

Я думаю, что это невозможно, потому что вам нужно создать собственный Принципал.Причина, по которой я думаю, что вы не можете сделать это в валидаторе, заключается в том, что я где-то читал, что валидатор работает в другом потоке, чем контекст операции.Я никогда не проверял это, но давайте предположим, что это действительно так.На основании этого предположения принципал, установленный в валидаторе, не будет использоваться в операции WCF.Вам необходимо создать настраиваемую авторизацию или поставщика настраиваемых ролей.

...