Фильтр авторизации WebApi с токеном в полезной нагрузке json

Я изучал авторизацию с помощью AspNetWebApi, и информации по этому вопросу немного.

У меня есть следующие варианты:

  1. Передать токен API в строке запроса
  2. Передать токен API в качестве заголовка
  3. Передайте токен API, используя Basic Auth
  4. Передайте токен API в полезную нагрузку запроса в json.

Какой обычно рекомендуется метод?

Меня также интересует пункт 4), как мне проверить полезную нагрузку json в методе OnAuthorization в AuthorizationFilterAttribute, чтобы проверить правильность токена API?


person jaffa    schedule 03.05.2012    source источник
comment
Что вы подразумеваете под токеном API? Вы имеете в виду файл cookie аутентификации?   -  person Aliostad    schedule 03.05.2012
comment
Просто GUID, который можно передавать в каждом запросе для аутентификации клиента.   -  person jaffa    schedule 04.05.2012


Ответы (1)


Если вам нужен действительно безопасный вариант авторизации, вам подойдет что-то вроде OAuth. В этом сообщении в блоге тщательный пример с использованием устаревшего веб-API WCF, но большую часть кода можно спасти. Или, по крайней мере, используйте базовую аутентификацию HTTP, как показано в этом запись в блоге. Как отмечает Алиостад, убедитесь, что вы используете HTTPS, если вы идете по маршруту базовой аутентификации, чтобы токен оставался в безопасности.

Если вы решите, что хотите свернуть свой собственный (который почти всегда будет гораздо менее безопасным, чем любой из вышеперечисленных вариантов), то ниже приведен пример кода того, что вам понадобится для AuthorizationHanlder, если вы идете по маршруту HTTP-заголовка. Имейте в виду, что существует большая вероятность того, что способ обработки UserPrinicipal в классах веб-API может измениться, поэтому этот код подходит только для первого предварительного выпуска. Вам нужно будет подключить AuthorizationHandler следующим образом:

    GlobalConfiguration.Configuration.MessageHandlers.Add(new AuthenticationHandler());

Код токена заголовка:

public class AuthenticationHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        var requestAuthTokenList = GetRequestAuthTokens(request);
        if (ValidAuthorization(requestAuthTokenList))
        {
            //TODO: implement a Prinicipal generator that works for you
            var principalHelper = GlobalConfiguration.Configuration
                .ServiceResolver
                    .GetService(typeof(IPrincipalHelper)) as IPrincipalHelper;

            request.Properties[HttpPropertyKeys.UserPrincipalKey] = 
                principalHelper.GetPrinicipal(request);

            return base.SendAsync(request, cancellationToken);
        }
        /*
        ** This will make the whole API protected by the API token.
        ** To only protect parts of the API then mark controllers/methods
        ** with the Authorize attribute and always return this:
        **
        ** return base.SendAsync(request, cancellationToken);
        */
        return Task<HttpResponseMessage>.Factory.StartNew(
            () => new HttpResponseMessage(HttpStatusCode.Unauthorized)
                {
                    Content = new StringContent("Authorization failed")
                });
    }

    private static bool ValidAuthorization(IEnumerable<string> requestAuthTokens)
    {
        //TODO: get your API from config or however makes sense for you
        var apiAuthorizationToken = "good token";
        var authorized = requestAuthTokens.Contains(apiAuthorizationToken);

        return authorized;
    }

    private static IEnumerable<string> GetRequestAuthTokens(HttpRequestMessage request)
    {
        IEnumerable<string> requestAuthTokens;
        if (!request.Headers.TryGetValues("SomeHeaderApiKey", out requestAuthTokens))
        {
            //Initialize list to contain a single not found token:
            requestAuthTokens = new[] {"No API token found"};
        }
        return requestAuthTokens;
    }
}
person Sixto Saez    schedule 03.05.2012
comment
Совершенно верно, Алиостад! Это настолько укоренилось, что я забыл даже упомянуть об этом. Спасибо!! - person Sixto Saez; 03.05.2012
comment
Есть ли недостаток между передачей токена в заголовке или использованием базовой аутентификации? Нельзя ли помещать токен API в json с запросом? Кроме того, как работает основной генератор? - person jaffa; 04.05.2012
comment
Я бы сказал, что разделение проблем было бы причиной того, что я бы не поместил токен авторизации в тело json. Если вы поместите его в тело, есть шанс, что он может быть частью того, что сериализуется в ваши модели. Если это то, что вы хотите, хотя, пойти на это. - person Sixto Saez; 04.05.2012