Как установить личность / имя пользователя в ServiceAuthorizationManager? - PullRequest
4 голосов
/ 04 сентября 2011

У меня есть служба WCF 4.0 REST на стороне сервера (размещенная в IIS) и клиент Android.Клиент Android отправляет зашифрованный маркер безопасности в настраиваемом заголовке HTTP для аутентификации пользователя.Я реализовал пользовательский ServiceAuthorizationManager, который извлекает токен безопасности из заголовка.Токен содержит имя пользователя, которое я могу прочитать из токена:

public class MyAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        var requestMessage = operationContext.RequestContext.RequestMessage;
        var requestProperty = (HttpRequestMessageProperty)requestMessage
            .Properties[HttpRequestMessageProperty.Name];
        var token = requestProperty.Headers["X-MyCustomHeader"];
        if (!string.IsNullOrEmpty(token))
        {
            var userName = GetUserNameFromToken(token);
            if (!string.IsNullOrEmpty(userName))
            {
                // How to save userName now so that I can 
                // retrieve it in the service operations?
                return true;
            }
        }
        return false;
    }
}

Теперь моя проблема заключается в том, что мне также необходимо имя аутентифицированного пользователя в различных операциях службы (главным образом для доступа к данным профиля пользователя) иЯ планировал получить его таким образом:

public void MyServiceOperation()
{
    string userName = OperationContext.Current
        .ServiceSecurityContext.PrimaryIdentity.Name;

    // check profile store for that userName and do something depending on
    // profile settings
}

Как я могу установить это имя пользователя в CheckAccessCore?

Очень наивное испытание, подобное этому ...

operationContext.ServiceSecurityContext.PrimaryIdentity.Name = userName;

... не работает, потому что PrimaryIdentity.Name только для чтения.Я предполагаю, что требуется более сложный код.

Ответы [ 2 ]

3 голосов
/ 09 сентября 2011

После некоторого исследования я не нашел способа установить идентичность в ServiceAuthorizationManager.CheckAccessCore.Этот метод, кажется, вызывается слишком поздно в конвейере обработки, когда идентификация пользователя уже установлена ​​(возможно, «Аноним» (IsAuthenticated is false)) и больше не может быть изменена.ServiceAuthorizationManager предназначен для авторизации, а не аутентификации, поэтому он не подходит для реализации пользовательской аутентификации.

Я наконец-то нашел три возможных пути решения моей проблемы:

  1. Как объяснено в статье, ссылки на которую есть в ответе @ TheCodeKing, использование начального набора WCF REST предоставляет возможность написать пользовательский RequestInterceptor, который достаточно рано подключается к конвейеру, позволяет получить доступ к входящему запросу и позволяет установитьличность пользователя на основе, например, пользовательских заголовков HTTP.К сожалению, стартовый комплект WCF REST устарел (основан на WCF 3.5), и разработка, по-видимому, была прекращена.Некоторые из его функций были включены в WCF 4.0, но некоторые нет, и RequestInterceptor среди них.Тем не менее, я использовал это решение сейчас и смешал сборку Microsoft.ServiceModel.Web из набора для начинающих с моим решением WCF 4.0.Кажется, он работает до сих пор после нескольких простых тестов.

  2. Если идентификация не является действительно необходимой, а только имя пользователя, простой «трюк» / «хак», чтобы написать пользователюимя в новом заголовке запроса работает (также в CheckAccessCore):

    // ...
    var userName = GetUserNameFromToken(token);
    if (!string.IsNullOrEmpty(userName))
    {
        requestProperty.Headers["X-UserName"] = userName;
        return true;
    }
    // ...
    

    А затем в методах обслуживания:

    public void MyServiceOperation()
    {
        string userName = WebOperationContext.Current.IncomingRequest
            .Headers["X-UserName"];
        // ...
    }
    
  3. Еще и еще нижеОпция level будет заключаться в написании пользовательского HttpModule, который перехватывает входящий запрос и устанавливает идентификатор.Примером того, как это может выглядеть, является здесь от команды Microsoft Pattern & Practices (см. Пример «Код модуля HTTP» в середине статьи).

2 голосов
/ 04 сентября 2011

Взгляните на эту статью. Здесь приведены примеры настройки экземпляра IAuthorizationPolicy. Создавая собственную реализацию, вы можете управлять созданием экземпляров IPrincipal и IIdentity, которые передаются в контексте. Это все подключено от сервисного перехватчика.

internal class AuthorizationPolicyFactory
{
   public virtual IAuthorizationPolicy Create(Credentials credentials)
   {
      var genericIdentity = new GenericIdentity(credentials.UserName);
      var genericPrincipal = new GenericPrincipal(genericIdentity,
                                                  new string[] { });
      return new PrincipalAuthorizationPolicy(genericPrincipal);
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...