【问题标题】:Force the authentication middleware to only accept encrypted tokens强制认证中间件只接受加密令牌
【发布时间】:2019-04-29 12:28:38
【问题描述】:

根据this question,我正在使用下面的sn-p 对JWToken 进行签名和加密。

var claims = new Claim[] { new SomeClaimes() };
var scKey = Encoding.UTF8.GetBytes("SOME KEY");
var ecKeyTemp = Encoding.UTF8.GetBytes("SOME OTHER KEY");

byte[] ecKey = new byte[256 / 8];
Array.Copy(ecKeyTemp, ecKey, 256 / 8);

var tokenDescriptor = new SecurityTokenDescriptor {
    Subject = new ClaimsIdentity(claims),
    SigningCredentials = new SigningCredentials(
        new SymmetricSecurityKey(
            scKey),
            SecurityAlgorithms.HmacSha512),
    EncryptingCredentials = new EncryptingCredentials(
        new SymmetricSecurityKey(
            ecKey),
            SecurityAlgorithms.Aes256KW,
            SecurityAlgorithms.Aes256CbcHmacSha512), 
    Issuer = "My Jwt Issuer",
    Audience = "My Jwt Audience",
    IssuedAt = DateTime.UtcNow,
    Expires = DateTime.Now.AddDays(7),
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor);
var jwt = tokenHandler.WriteToken(token);

这是我的服务注册:

services
.AddAuthentication(o => {
    o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(cfg => {
    cfg.RequireHttpsMetadata = false;
    cfg.SaveToken = true;
    cfg.TokenValidationParameters = new TokenValidationParameters {
        ValidIssuer = "My Jwt Issuer",
        ValidAudience = "My Jwt Audience",
        IssuerSigningKey = new SymmetricSecurityKey(SameKeyAsGenerating)),
        TokenDecryptionKey = new SymmetricSecurityKey(SameKeyAsGenerating),
        ClockSkew = TimeSpan.Zero, 
        RequireSignedTokens = true,
        RequireExpirationTime = true,
        SaveSigninToken = true,
        ValidateActor = true,
        ValidateAudience = true,
        ValidateIssuer = true,
        ValidateIssuerSigningKey = true,
        ValidateLifetime = true,
        ValidateTokenReplay = true,
    };
});

问题在于身份验证层将加密和未加密的令牌都作为授权进行身份验证。我的意思是当我创建一个没有EncryptingCredentials 的令牌(只是一个签名的令牌,没有加密)时,令牌仍然有效并且请求被授权。问题是如何强制认证层只接受签名加密的令牌,拒绝刚刚签名的未加密令牌?

更新:解决方案:

感谢sellotape's answer,我实现了这个JwtEncryptedSecurityTokenHandler

public class JwtEncryptedSecurityTokenHandler : JwtSecurityTokenHandler {

    [DebuggerStepThrough]
    public override ClaimsPrincipal ValidateToken(string token, TokenValidationParameters validationParameters, out SecurityToken validatedToken) {
        if (string.IsNullOrWhiteSpace(token))
            throw new ArgumentNullException(nameof (token));

        if (validationParameters == null)
            throw new ArgumentNullException(nameof (validationParameters));

        if (token.Length > MaximumTokenSizeInBytes)
            throw new ArgumentException(
                $"IDX10209: token has length: '{token.Length}' which is larger than the MaximumTokenSizeInBytes: '{MaximumTokenSizeInBytes}'.");

        var strArray = token.Split(new[] { '.' }, 6);
        if (strArray.Length == 5)
            return base.ValidateToken(token, validationParameters, out validatedToken);

        throw new SecurityTokenDecryptionFailedException();
    }
}

并在Startup.ConfigureServices()中使用了新的处理程序:

.AddJwtBearer(cfg => {
    cfg.RequireHttpsMetadata = false;
    // other configurations...
    cfg.SecurityTokenValidators.Clear();
    cfg.SecurityTokenValidators.Add(new JwtEncryptedSecurityTokenHandler());
});

有关更多解释,请参阅接受的答案。

【问题讨论】:

    标签: c# authentication .net-core jwt netcoreapp2.1


    【解决方案1】:

    我确信有几种方法可以做到这一点,但怎么样:

    • 实现ISecurityTokenValidator,可能继承自SecurityTokenHandler;所需的覆盖相当简单,大部分可以从JwtSecurityTokenHandler 复制。覆盖 ValidateToken() 并在 JWT 未加密时抛出**。

    • AddJwtBearer() configure-options 操作中添加新的处理程序/验证器:cfg.SecurityTokenValidators.Add(new RequireEncryptedTokenHandler());


    ** 如果您查看source for JwtSecurityTokenHandler.ValidateToken()(不确定您使用的是哪个版本,但我认为消息是相同的),似乎“已加密”被简单地确定为“有 5 个部分” ",这应该很容易在您的新处理程序中实现(复制/粘贴)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-05
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 2012-06-29
      相关资源
      最近更新 更多