在 WebAPI 的查询字符串中传递和验证 OWIN Bearer 令牌

Posted

技术标签:

【中文标题】在 WebAPI 的查询字符串中传递和验证 OWIN Bearer 令牌【英文标题】:Passing and verifying the OWIN Bearer token in Query String in WebAPI 【发布时间】:2014-03-22 10:23:00 【问题描述】:

短版: 我需要将 OWIN 轴承令牌作为查询参数而不是在请求标头中传递和验证。

然后如何根据该令牌字符串获取授权方法?

背景: 我想调用 webapi 方法将文件下载为流(并且不希望用户从已知文件位置下载它)。

如果我还需要设置自定义请求标头(即不记名令牌),我无法使其工作。

我应该能够在查询字符串中传递令牌 - 但不知道如何获取该令牌然后对用户进行身份验证。

我需要过滤吗?我需要特殊索赔等吗? webapi方法是否需要包含“access_token”作为函数参数之一?

【问题讨论】:

【参考方案1】:

我在这里写过它是如何工作的: http://leastprivilege.com/2013/10/31/retrieving-bearer-tokens-from-alternative-locations-in-katanaowin/

【讨论】:

【参考方案2】:

为了完整起见,here's 另一个巧妙的解决方案。

摘录:

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

【讨论】:

非常感谢,我将它包含在我自己的 IAppBuilder 扩展方法中:public static void UseQueryStringAuthentication(this IAppBuilder app),以便我可以遵循与 app.UseQueryStringAuthentication() 相同的做法。还值得一提的是,当我们拦截调用时,我们必须在调用身份验证机制之前将其放入管道中。所以我把它作为我的 Startup.Auth 文件中的第一项。 这必须出现在调用 app.UseOAuthBearerTokens 之前 是的,非常重要,这是在 app.UseOAuthBearerTokens(OAuthOptions) 命令之前 这行得通,非常感谢。但有一个问题。假设用户生成一个 PDF 文件以供下载,其中包含资源链接(即“/downloads/file_id”)。这适用于您的方法,但令牌已过期。一段时间后,如果我尝试打开此 PDF 中的链接,它将再次未经授权。有什么想法可以解决这个问题吗? @Nexus 是的,包含不记名令牌的 URL 将过期。要么使用 401“未授权”响应来处理此问题,重定向到您的登录页面,然后可以使用新令牌重定向回 /downloads/... 链接。或者使用不安全的 API 来提供下载,但不是采用 file_id,您可以生成一个唯一令牌并通过您的数据库(或其他)将其与您的文件相关联,然后创建一个 /downloads/file_token 端点。这种解耦将通过混淆(即人们猜测文件 ID)保护您的 API,并允许您禁用/过期下载链接。【参考方案3】:

或者这样做

    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
    
        Authority = IdentityConfig.Authority,
        RequiredScopes = new[]  "api" ,
        TokenProvider = new OAuthBearerAuthenticationProvider
        
            OnRequestToken = ctx =>
            
                if (String.IsNullOrWhiteSpace(ctx.Token) && ctx.Request.QueryString.HasValue)
                
                    NameValueCollection parsedQuery = HttpUtility.ParseQueryString(ctx.Request.QueryString.Value);
                    ctx.Token = parsedQuery["access_token"];
                

                return Task.FromResult(0);
            
        
    );

【讨论】:

以上是关于在 WebAPI 的查询字符串中传递和验证 OWIN Bearer 令牌的主要内容,如果未能解决你的问题,请参考以下文章

通过查询字符串传递“承载”时,SignalR 身份验证失败

如何在.net6webapi中配置Jwt实现鉴权验证

HttpClient 将 ClaimsIdentity 传递给另一个 WebApi

您如何满足 WebApi 查询字符串中的 AND 和 OR 搜索?

如何在WebAPI的控制器的GET请求中传递参数

WebAPI 和 401 与 200