2014-02-21 1 views
4

У меня проблема с моим проектом Web Api. У меня есть файлы, хранящиеся в моей базе данных, и вы хотите их напрямую вызвать в новом окне для просмотра/сохранения (например:/api/Files/5 - 5 beeing the FileId). NET Web API 2 OWIN-указатель на токен аутентификации прямой вызов

У меня все время работает с указателем-носителем для моих общих запросов AJAX с AngularJS для обычных Данных, и это работает как шарм. Для файла я создал контроллер, который показывает файл в браузере с соответствующим MIME-типом. Но теперь, когда я изменил действие на [Авторизовать], я получил Access Denied, который является правильным, потому что я не передал access_token в HTTP-заголовке.

Я сделал довольно некоторое исследование, если можно пропустить токен через строку запроса, но не нашел ничего полезного.

Теперь мой план состоит в том, чтобы удалить атрибут [Авторизовать] от моего контроллера и попытаться проверить токен самостоятельно, но я не знаю, как это сделать.

Кто-нибудь знает, как я могу заставить его работать?

ответ

0

Хотя я не уверен, что это очень хорошая идея, вы можете реализовать DelegatingHandler, чтобы достичь того, что ищете.

public class QueryStringBearerToken : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     var bearerToken = request.GetQueryNameValuePairs() 
           .Where(kvp => kvp.Key == "bearerToken") 
           .Select(kvp => kvp.Value) 
           .FirstOrDefault(); 

     if(!String.IsNullOrEmpty(bearerToken)) 
     { 
      request.Headers.Add("Authorization", "Bearer " + bearerToken); 
     } 
     return base.SendAsync(request, cancellationToken); 
    } 
} 

Этот обработчик будет искать строку запроса с именем "bearerToken" и, если он существует, будет добавить его в заголовок запроса для последующих обработчиков/фильтра для обработки. Сначала вы можете проверить, если заголовок уже присутствует и не переопределяется в этом случае. Вы можете добавить этот обработчик в вашей фазе конфигурации обычным способом:

config.MessageHandlers.Insert(0, new QueryStringBearerToken()); 

Запрос на /YourRoute?bearerToken=theToken будет проходить в DelegatingHandler, добавляя маркер, переданный в строку запроса в список заголовков в исходном запросе а обычная аутентификация маркера предъявителя будет искать заголовок и найти его.

+0

Thx для ответа. Это работает, но это не так. Отладчик попадает в код, и токен читается правильно, но у меня все еще появляется сообщение об ошибке, которое я не авторизовался. Если я пытаюсь жестко кодировать токен, я получаю дублируемую ошибку для запросов, которые фактически имеют атрибут authorzation ... Мое предположение заключается в том, что этот обработчик срабатывает после проверки? – Marvin

+0

@Marvin Ожидается дублирующаяся ошибка. Как я уже сказал, я не поместил логику для обработки случая, когда в запросе уже есть заголовок авторизации. Сначала размещение обработчика делегирования в конвейере ('Insert (0, ...)') должно выполняться до того, как авторизация начнется. –

+0

Другим важным моментом является кодирование токена, если оно передано в строке запроса. Поскольку '=' может быть частью токена, он может усечь значение из 'GetQueryNameValuePairs()'. Вы должны проверить, совпадает ли маркер, который вы передаете в строке запроса, как переменная 'bearerToken', когда вы устанавливаете точку останова. Если это так, это объясняет 401, поскольку токен-носитель не распознается. –

23

Я реализовал маркер аутентификации знаменосцем в мое приложение (AngularJS, WebAPI 2) и у меня была аналогичная проблема - мне нужно, чтобы позволить загружая файлы, нажав на ссылку. Когда вы нажимаете на заголовки, ссылки не отправляются. :( Итак, я послал значение маркера в строке запроса, чтобы загрузить файл

.../mywebapp/API/файлы/GetFile/3? Access_token = jaCOTrGsaak6Sk0CpPc1 ...

и установить «Авторизация . "заголовок лексем значение в Startup.Auth.cs Вот код:

public void ConfigureAuth(IAppBuilder app) 
{ 
    //It needs for file downloads 
    app.Use(async (context, next) => 
    { 
     if (context.Request.QueryString.HasValue) 
     { 
      if (string.IsNullOrWhiteSpace(context.Request.Headers.Get("Authorization"))) 
      { 
       var queryString = HttpUtility.ParseQueryString(context.Request.QueryString.Value); 
       string token = queryString.Get("access_token"); 

       if (!string.IsNullOrWhiteSpace(token)) 
       { 
        context.Request.Headers.Add("Authorization", new[] { string.Format("Bearer {0}", token) }); 
       } 
      } 
     } 

     await next.Invoke(); 
    }); 
    // Enable the application to use bearer tokens to authenticate users 
    app.UseOAuthBearerTokens(OAuthOptions); 
} 
+1

Это работало для меня и было самым простым из нескольких вариантов, которые я пробовал. Тем не менее, есть другие подходы, которые могут быть лучшими, поэтому не используйте это, пока не проверите альтернативные методы для себя. –

+1

Хотел бы я проголосовать за это несколько раз. Умный, лаконичный, элегантный ... и т. Д. :) – Korayem

+0

@johnwest, пожалуйста, поделитесь с нами альтернативными методами – Korayem

1

для ASP .Net Ядра я сделал что-то подобное на основе ответа Форвард«s

E Метод XTension

public static void UseQueryStringBearerValidation(this IApplicationBuilder app) 
    { 
     //It needs for file downloads 
     app.Use(async (context, next) => 
     { 
      if (context.Request.QueryString.HasValue) 
      { 
       if (string.IsNullOrWhiteSpace(context.Request.Headers["Authorization"].ToString())) 
       { 
        var queryString = QueryHelpers.ParseQuery(context.Request.QueryString.Value); 
        var token = queryString["access_token"].ToString(); 

        if (!string.IsNullOrWhiteSpace(token)) 
        { 
         context.Request.Headers.Add("Authorization", new[] {$"Bearer {token}"}); 
        } 
       } 
      } 

      await next(); 
     }); 
    } 

Использование

StartUp.cs -> Настроить() метод

  app.UseCustomExceptionHandler(); 
      app.UseQueryStringBearerValidation(); // <-- add before Jwt Handler 
      app.UseCustomJwtBearerValidation(); 
      app.AddHttpContextProperties(); 
      app.UseStaticFiles(); 
      app.UseMvc(MiddlewareAppConfiguration.AddRouteMappings); 
Смежные вопросы