2014-02-21 62 views
4

我的Web Api项目出现问题。 我有存储在我的数据库中的文件,并希望直接在新窗口中查看/保存(URL像:/ api/Files/5 - 5 beeing FileId).NET Web API 2 OWIN承载令牌认证直接调用

我得到everthing与持票人令牌对于我的一般AJAX请求与AngularJS正常数据,它的作品就像一个魅力。对于该文件,我创建了一个Controller,它在浏览器中显示相应的MIME-Type文件。但是现在,我将操作更改为[授权],我得到了拒绝访问,这是正确的,因为我没有在HTTP头中传递access_token。

我做了相当多的研究,如果可以通过查询字符串传递令牌,但没有找到有用的东西。

现在我的计划是从我的控制器中删除[Authorize]属性,并尝试自己验证令牌,但我不知道如何。

任何人都知道我可以如何让它工作?

回答

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 for the reply。它有点有用,但它没有。 调试器击中代码和令牌得到正确读取,但我仍然收到一个错误消息,我没有授权。 如果我试图对代码进行硬编码,那么对于实际上拥有authorzation属性的请求会出现重复错误......我的猜测是此代码处理器在验证后启用了? – Marvin

+0

@Marvin预计会出现重复错误。正如我所说的,我没有把逻辑处理在请求中已经有Authorization头部的情况下。将第一个委托处理程序放入管道('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的核心我不喜欢的东西此基础上正向的回答

Ë 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(); 
     }); 
    } 

使用

启动。cs - > Configure()方法

  app.UseCustomExceptionHandler(); 
      app.UseQueryStringBearerValidation(); // <-- add before Jwt Handler 
      app.UseCustomJwtBearerValidation(); 
      app.AddHttpContextProperties(); 
      app.UseStaticFiles(); 
      app.UseMvc(MiddlewareAppConfiguration.AddRouteMappings);