【问题标题】:Ignore JWT Bearer token signature (i.e. don't validate token)忽略 JWT Bearer 令牌签名(即不验证令牌)
【发布时间】:2018-09-30 15:17:27
【问题描述】:

我有一个位于 API 网关后面的 API。 API Gateway 在将请求传递给 API 之前验证承载令牌。

我的 API 使用 asp.net core 2.0 本机身份验证和基于声明的授权框架。从 JWT 令牌获取声明的繁重工作由 Microsoft.AspNetCore.Authentication.JwtBearer 中的中间件完成。

这个中间件可以配置为忽略令牌的过期日期,也可以指定一个本地公钥,这样就不需要联系令牌授权机构来获取一个,但是可以只禁用令牌上的签名验证?

这将允许在开发中使用未签名的令牌进行临时测试,并防止在生产中进行双重验证(网关和 API)。

【问题讨论】:

  • 我认为如果您清除默认令牌验证器并提供您自己的 ISecurityTokenValidator 跳过任何验证应该这样做。 github.com/AzureAD/…
  • @Eli Algranti 能找到任何方法吗?我目前遇到了同样的问题。
  • 只是为了分享我的设计。我也在使用这种方法来禁用网关和 api 级别的双重验证。我使用 nginx+ 作为 api 网关,identityserver4 来生成令牌。 Api 网关将进行验证。这将消除在 api 级别完成令牌验证的需要(它可以来自 .net、java 等)

标签: c# asp.net-core


【解决方案1】:

试试这个。经过这么多尝试,我终于让它工作了。

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

【讨论】:

  • 我已经离开了这个项目,所以我无法验证你的答案,所以我会接受它并相信你的话。其他人可能会觉得这很有用。
  • 我为此苦苦挣扎了 2 天的不间断测试,终于让它发挥作用。呜呜呜……
  • 这也适用于 asp.net core 3.1,感谢您的研究...为我节省了大量时间
  • ValidateTokenReplay = false 也是需要的,它保证 User 对象和 Claims 将被初始化。此外,如果我们想跳过验证,ValidIssuer(不是 bool 标志)和 ValidAudience 对于我们的案例是可选的。
  • 虽然这对我有用,但我真的不明白这里发生了什么。有什么解释吗?
【解决方案2】:

我能够稍微清理一下代码,表明我们可以只更改标志并且在设置标志时更加一致。

services.AddAuthentication(o =>
{
    o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
    .AddJwtBearer(o =>
    {
        o.RequireHttpsMetadata = false;
        o.SaveToken = true;
        o.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateIssuerSigningKey = false,
            ValidateLifetime = false,
            RequireExpirationTime = false,
            RequireSignedTokens = false
        };
    });

【讨论】:

  • 欢迎来到 SO!当您发布答案并且还有更多答案时,请公开您的优点。并尝试稍微解释一下您的代码。
  • 希望这更好@DavidGarcíaBodego。这绝对是更多的代码清理。
【解决方案3】:

您可以使用JwtBearerOptions.TokenValidationParameters 设置令牌验证。您可以从the class definition 查看所有可用参数。

包含一组参数,供 Microsoft.IdentityModel.Tokens.SecurityTokenHandler 在验证 Microsoft.IdentityModel.Tokens.SecurityToken 时使用。

如果您想完全禁用验证,请将所有 ValidateXXXRequireXXX 布尔属性设置为 false:

.AddJwtBearer("<authenticationScheme>", configureOptions =>
{
   options.TokenValidationParameters.ValidateActor = false;
   options.TokenValidationParameters.ValidateAudience = false;
   options.TokenValidationParameters.ValidateIssuerSigningKey = false;
   ...
}

作为另一种选择,您可以通过将自己的实现设置为 JwtBearerOptions.SignatureValidator 来覆盖默认令牌签名验证:

// Gets or sets a delegate that will be used to validate the signature of the token.
//
// Remarks:
//  If set, this delegate will be called to signature of the token, instead of normal
//  processing.
public SignatureValidator SignatureValidator { get; set; }

其中SignatureValidator委托定义为:

public delegate SecurityToken SignatureValidator(string token, TokenValidationParameters validationParameters);

【讨论】:

  • 感谢您的回复。我已经在使用JwtBearerOptions.TokenValidationParameters 来禁用过期时间验证,但是我找不到这个类的好文档。您知道哪个选项(如果有)禁用检查令牌签名吗?我希望找到已经实际完成并检查过的人。
  • @EliAlgranti 有更新帖子。您可以从类定义中了解每个属性(source code 可用)
猜你喜欢
  • 2019-11-01
  • 2018-05-29
  • 2019-06-14
  • 2015-11-04
  • 2017-05-14
  • 2019-06-23
  • 2017-09-18
  • 2020-05-11
  • 1970-01-01
相关资源
最近更新 更多