如何加密JWT安全令牌?

Qué*_*dre 21 c# security wif jwt

我需要通过签名和加密来保护我的网络令牌.我编写了下一行代码:

var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
      Subject = new ClaimsIdentity(new[]
         {
             new Claim(ClaimTypes.Name, owner.Name),
             new Claim(ClaimTypes.Role, owner.RoleClaimType),
             new Claim("custom claim type", "custom content")
         }),
      TokenIssuerName = "self",
      AppliesToAddress = "http://www.example.com",
      Lifetime = new Lifetime(now, now.AddSeconds(60 * 3)),
      EncryptingCredentials = new X509EncryptingCredentials(new X509Certificate2(cert)),
      SigningCredentials = new X509SigningCredentials(cert1)
};
var token = (JwtSecurityToken)tokenHandler.CreateToken(tokenDescriptor);            
var tokenString = tokenHandler.WriteToken(token);
Run Code Online (Sandbox Code Playgroud)

所以,我正在使用一些生成的证书makecert.exe.然后我用另一个读取令牌字符串JwtSecurityTokenHandler:

var tokenHandlerDecr = new JwtSecurityTokenHandler();
var tok = tokenHandlerDecr.ReadToken(tokenString);
Run Code Online (Sandbox Code Playgroud)

并且令牌内容未加密(我可以tok在调试器下看到变量中的json ).我究竟做错了什么?如何加密令牌数据?

Ame*_*mey 29

我知道这是一篇旧帖子,但如果有人还在寻找答案的话,我会加上我的答案.

此问题在Microsoft.IdentityModel.Tokens版本5.1.3中得到解决.CreateJwtSecurityToken函数中有一个重载方法,它接受加密凭证来加密令牌.

如果接收方未验证签名并尝试按原样读取JWT,则声明为空.以下是代码段:

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;

const string sec = "ProEMLh5e_qnzdNUQrqdHPgp";
const string sec1 = "ProEMLh5e_qnzdNU";
var securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec));
var securityKey1 = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec1)); 

var signingCredentials = new SigningCredentials(
    securityKey,
    SecurityAlgorithms.HmacSha512);

List<Claim> claims = new List<Claim>()
{
    new Claim("sub", "test"),
};

var ep = new EncryptingCredentials(
    securityKey1,
    SecurityAlgorithms.Aes128KW,
    SecurityAlgorithms.Aes128CbcHmacSha256);

var handler = new JwtSecurityTokenHandler();

var jwtSecurityToken = handler.CreateJwtSecurityToken(
    "issuer",
    "Audience",
    new ClaimsIdentity(claims),
    DateTime.Now,
    DateTime.Now.AddHours(1),
    DateTime.Now,
    signingCredentials,
    ep);


string tokenString = handler.WriteToken(jwtSecurityToken);

// Id someone tries to view the JWT without validating/decrypting the token,
// then no claims are retrieved and the token is safe guarded.
var jwt = new JwtSecurityToken(tokenString);
Run Code Online (Sandbox Code Playgroud)

以下是验证/解密令牌的代码:

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;

const string sec = "ProEMLh5e_qnzdNUQrqdHPgp";
const string sec1 = "ProEMLh5e_qnzdNU";
var securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec));
var securityKey1 = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec1));

// This is the input JWT which we want to validate.
string tokenString = string.Empty;

// If we retrieve the token without decrypting the claims, we won't get any claims
// DO not use this jwt variable
var jwt = new JwtSecurityToken(tokenString);

// Verification
var tokenValidationParameters = new TokenValidationParameters()
{
    ValidAudiences = new string[]
    {
        "536481524875-glk7nibpj1q9c4184d4n3gittrt8q3mn.apps.googleusercontent.com"
    },
    ValidIssuers = new string[]
    {
        "https://accounts.google.com"
    },
    IssuerSigningKey = securityKey,
    // This is the decryption key
    TokenDecryptionKey = securityKey1
};

SecurityToken validatedToken;
var handler = new JwtSecurityTokenHandler();

handler.ValidateToken(tokenString, tokenValidationParameters, out validatedToken);
Run Code Online (Sandbox Code Playgroud)


Hun*_*ach 12

试试下面的例子

2019 年 7 月更新:.NET Core、Asp.net Core

1.创建JWT

private string CreateJwt(string sub, string jti, string issuer, string audience)
{
    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, sub),
        new Claim(JwtRegisteredClaimNames.Jti, jti),
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS"));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var encryptingCredentials = new EncryptingCredentials(key, JwtConstants.DirectKeyUseAlg, SecurityAlgorithms.Aes256CbcHmacSha512);

    var jwtSecurityToken = new JwtSecurityTokenHandler().CreateJwtSecurityToken(
        issuer,
        audience,
        new ClaimsIdentity(claims),
        null,
        expires: DateTime.UtcNow.AddMinutes(5),
        null,
        signingCredentials: creds,
        encryptingCredentials: encryptingCredentials
        );
    var encryptedJWT = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);

    return encryptedJWT;
}
Run Code Online (Sandbox Code Playgroud)

2.添加到ConfigureServices(IServiceCollection services)Startup.cs

    services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,

        ValidIssuer = (string)Configuration.GetSection("JwtToken").GetValue(typeof(string), "Issuer"),
        ValidAudience = (string)Configuration.GetSection("JwtToken").GetValue(typeof(string), "Audience"),
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS")),
        TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS")),
        ClockSkew = TimeSpan.FromMinutes(0),
    };
});
Run Code Online (Sandbox Code Playgroud)


Bro*_*len 7

我的理解是,微软的JWT实现目前不支持加密(仅签名).

  • 有没有其他方法可以实现此功能?任何可以使用或可能覆盖JwtSecurityTokenHandler的库? (2认同)
  • Microsoft.IdentityModel.Tokens版本5.1.3中解决了此问题.有关详细信息,请参阅我的回答 (2认同)