简体   繁体   English

.NET Web API 2 OWIN承载令牌身份验证直接调用

[英].NET Web API 2 OWIN Bearer Token Authentication direct call

I have a problem with my Web Api Project. 我的Web Api项目有问题。 I have files stored in my Database and want to call them directly in a new window to view/save (URL like : /api/Files/5 - 5 beeing the FileId) 我将文件存储在数据库中,并希望在新窗口中直接调用它们以查看/保存(URL:/ api / Files / 5-5 beeing FileId)

I got everthing working with the Bearer Token for my general AJAX requests with AngularJS for normal Data and it works like a charm. 对于AngularJS对于常规数据的常规AJAX请求,我可以使用Bearer Token进行任何工作,它的工作原理就像一个魅力。 For the file I created a Controller that shows the file in the browser with the corresponding MIME-Type. 我为该文件创建了一个Controller,该Controller在浏览器中显示相应的MIME类型的文件。 But now that I changed the action to [Authorize] I get an Access Denied which is correct because I didnt pass an access_token in the HTTP-Header. 但是,现在我将操作更改为[Authorize],我得到了正确的访问被拒绝,因为我没有在HTTP标头中传递access_token。

I did quite some research if it is possible to pass the Token via the querystring but didn't find anything helpful. 如果可以通过查询字符串传递令牌,我做了很多研究,但没有发现任何帮助。

Now my plan is to remove the [Authorize] Attribute from my Controller and try to validate the token myself but I don't know how. 现在,我的计划是从控制器中删除[Authorize]属性,然后尝试自己验证令牌,但我不知道如何做。

Anyone know how I can get it to work? 有人知道我怎样才能使它工作吗?

I implemented bearer token authentication in my app (AngularJS, WebAPI 2) and I had similar problem - I needed to allow downloading files by clicking on a link. 我在应用程序(AngularJS,WebAPI 2)中实现了承载令牌身份验证,并且遇到了类似的问题-我需要允许通过单击链接来下载文件。 When you click on a link headers are not sent. 当您单击链接时,不发送标题。 :( So, I sent the token value in a query string to download a file :(因此,我在查询字符串中发送了令牌值以下载文件

.../mywebapp/api/files/getfile/3?access_token=jaCOTrGsaak6Sk0CpPc1... ... / mywebapp / api / files / getfile / 3?access_token = jaCOTrGsaak6Sk0CpPc1 ...

and set "Authorization" header to the token value in Startup.Auth.cs. 并将“授权”标头设置为Startup.Auth.cs中的令牌值。 Here is the code: 这是代码:

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

For ASP .Net Core I did something like this based on Forward 's answer 对于ASP .Net Core,我根据Forward的回答做了类似的事情

Extension Method 扩展方式

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

Usage 用法

StartUp.cs -> Configure() method StartUp.cs-> Configure()方法

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

Although I'm not sure it's a very good idea, you could implementing a DelegatingHandler to achieve what you are looking for. 尽管我不确定这是一个好主意,但是您可以实现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);
    }
}

This handler will look for the query string named "bearerToken" and, if it exists, will add it to the request header for the subsequent handlers / filter to process. 该处理程序将查找名为"bearerToken"的查询字符串,如果存在,会将其添加到请求标头中,以供后续处理程序/过滤器处理。 You might want to check first if the header is already present and not override in this case. 您可能需要首先检查标题是否已经存在,并且在这种情况下不进行覆盖。 You can add this handler in your configuration phase in the usual fashion: 您可以按常规方式在配置阶段添加此处理程序:

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

A request for /YourRoute?bearerToken=theToken will pass in the DelegatingHandler , adding the token passed in the query string to the list of headers in the original request and the regular Bearer Token authentication will look for the header and find it. /YourRoute?bearerToken=theToken将在DelegatingHandler传递,将在查询字符串中传递的令牌添加到原始请求的标头列表中,常规的Bearer Token身份验证将查找标头并找到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM