【问题标题】:Fetch access token from authorization header without bearer prefix从没有承载前缀的授权标头中获取访问令牌
【发布时间】:2020-11-22 08:53:34
【问题描述】:

我正在为我的 .NET Core 项目使用 Microsoft.AspNetCore.Authentication.JwtBearerSystem.IdentityModel.Tokens.Jwt 包。

有一些受[Authorize]注解保护的控制器端点必须从请求中获取访问令牌。目前我正在以这种方式在我的控制器方法中获取访问令牌:

string accessTokenWithBearerPrefix = Request.Headers[HeaderNames.Authorization];
string accessTokenWithoutBearerPrefix = accessTokenWithBearerPrefix.Substring("Bearer ".Length);

我想知道是否有更好的“即用型”解决方案,因为使用上面的代码在从不记名令牌中获取子字符串时可能仍会导致错误。

【问题讨论】:

  • 可以看一下asp net core的代码。是开源的

标签: c# .net-core adal


【解决方案1】:

您可以使用以下代码获取安全令牌。

var stream ="[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var tokenS = handler.ReadToken(stream) as JwtSecurityToken;

另外,如果你想Ignore JWT Bearer token signature,你可以参考下面的代码:

public TokenValidationParameters CreateTokenValidationParameters()
{
    var result = new TokenValidationParameters
    {
    ValidateIssuer = false,
    ValidIssuer = ValidIssuer,

    ValidateAudience = false,
    ValidAudience = ValidAudience,

    ValidateIssuerSigningKey = false,
    //IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey)),
    //comment this and add this line to fool the validation logic
    SignatureValidator = delegate(string token, TokenValidationParameters parameters)
    {
        var jwt = new JwtSecurityToken(token);

        return jwt;
    },

    RequireExpirationTime = true,
    ValidateLifetime = true,

    ClockSkew = TimeSpan.Zero,
    };

    result.RequireSignedTokens = false;

    return result;
}

【讨论】:

  • 你介意解释一下这条线吗? var stream ="[encoded jwt]"; 编码的令牌从何而来?它来自Request.Headers[HeaderNames.Authorization] 吗?是不带承载前缀的完整访问令牌吗?
  • 它是没有承载前缀的完全访问令牌。
  • 从这里开始? Request.Headers[HeaderNames.Authorization] ?
  • 是的,删除不记名前缀。
  • 也许我误解了您的解决方案,但我正在寻找一种方法来从访问令牌中删除不记名前缀,而无需自己动手。我尝试了您的代码,但不幸的是我遇到了一个异常,我将其添加为评论 hatebin.com/dhkiehygvw
【解决方案2】:

这是一种无需进入标题字典即可获取标题的巧妙方法。这也将让框架解析令牌,我相信这是您正在寻找的:

[HttpGet, Route("someEndpoint")]
public IActionResult SomeEndpoint([FromHeader] string authorization)
{

    if(AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
    {
        // we have a valid AuthenticationHeaderValue that has the following details:

        var scheme = headerValue.Scheme;
        var parameter = headerValue.Parameter;

        // scheme will be "Bearer"
        // parmameter will be the token itself.
    }

    return Ok();
}

你也可以用老派的方式抓取标题:

[HttpGet, Route("someEndpoint")]
public IActionResult SomeEndpoint()
{
    var authorization = Request.Headers[HeaderNames.Authorization];

    if (AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
    {
        // we have a valid AuthenticationHeaderValue that has the following details:

        var scheme = headerValue.Scheme;
        var parameter = headerValue.Parameter;

        // scheme will be "Bearer"
        // parmameter will be the token itself.
    }

    return Ok();
}

很好的是AuthenticationHeaderValue.TryParse 将涵盖奇怪的情况,例如方案和令牌之间是否有多个空格,或者方案之前有空格,或者令牌之后有空格......并将其修剪为你。

现在,这些情况不应该发生,但是......它们可能,并且accessTokenWithBearerPrefix.Substring("Bearer ".Length); 的执行将失败。这就是为什么我相信您想要一种更具体的方式来解析令牌。

【讨论】:

  • 读者:很好的答案,但请注意,如果字符串缺少像“Bearer”这样的模式前缀,那么 AuthenticationHeaderValue.TryParse(string) 错误地将令牌分配给模式属性并设置参数属性(令牌)为空。所以看起来模式前缀是必需的,并且需要额外的检查。 +1
【解决方案3】:

您可以将Startup.cs中的SaveToken设置为true

services.AddAuthentication()
    .AddJwtBearer(options =>
    {
        // your other config
        options.SaveToken = true;
    });

并使用GetTokenAsync 方法从HttpContext 获取访问令牌。

using Microsoft.AspNetCore.Authentication;

public class SampleController : Controller
{
    public void Index()
    {
        var accessToken = HttpContext.GetTokenAsync("access_token");
    }
}

【讨论】:

    猜你喜欢
    • 2021-01-17
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 2018-06-13
    • 2017-11-13
    相关资源
    最近更新 更多