dnx451 RC1 InMemorySymmetricSecurityKey 发生了啥?

Posted

技术标签:

【中文标题】dnx451 RC1 InMemorySymmetricSecurityKey 发生了啥?【英文标题】:dnx451 RC1 What happened to InMemorySymmetricSecurityKey?dnx451 RC1 InMemorySymmetricSecurityKey 发生了什么? 【发布时间】:2016-05-29 13:06:22 【问题描述】:

我一直在尝试使用简单的密钥创建和签署 JwtSecurityToken。经过大量研究,我发现的所有示例似乎都使用 InMemorySymmetricSecurityKey 类,但不幸的是,该类似乎不存在于最新版本的 System.IdentityModel 库中。 p>

这些是我正在使用的依赖项:

"System.IdentityModel.Tokens": "5.0.0-rc1-211161024",
"System.IdentityModel.Tokens.Jwt": "5.0.0-rc1-211161024"

我也尝试过使用它的基类SymmetricSecurityKey,但在尝试创建令牌时出现以下异常:

"Value cannot be null.\r\nParameter name: IDX10000: The parameter 'signatureProvider' cannot be a 'null' or an empty object."

这是引发异常的代码:

public static string CreateTokenHMAC()

    HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String("test"));

    var key = new SymmetricSecurityKey(hmac.Key);

    var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

    JwtSecurityToken token = _tokenHandler.CreateJwtSecurityToken(new SecurityTokenDescriptor()
    
        Audience = AUDIENCE,
        Issuer = ISSUER,
        Expires = DateTime.UtcNow.AddHours(6),
        NotBefore = DateTime.Now,
        Claims = new List<Claim>()
        
            new Claim(ClaimTypes.Email, "johndoe@example.com")
        ,
        SigningCredentials = signingCredentials
    );

    return _tokenHandler.WriteToken(token);

这是我第一次使用 JwtSecurityToken,所以我的猜测是我可能在某处遗漏了一步

【问题讨论】:

【参考方案1】:

这应该可以工作(注意这需要 RC2 包 > 304180813)

var handler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor

    Subject = new ClaimsIdentity(
        new Claim[]  new Claim(ClaimTypes.NameIdentifier, "bob") ),
    SigningCredentials = new SigningCredentials(
        new SymmetricSecurityKey(new byte[256]),
        SecurityAlgorithms.HmacSha256)
;

var jwt = handler.CreateEncodedJwt(tokenDescriptor);

【讨论】:

【参考方案2】:

我无法使用已接受答案中提供的 RsaSecurityKey 示例使其正常工作,但这对我来说确实有效(使用 System.IdentityModel.Tokens.Jwt v5.1.3)。

var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("test"));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

var securityTokenDescriptor = new SecurityTokenDescriptor()

    Subject = new ClaimsIdentity(new List<Claim>()
    
        new Claim(ClaimTypes.NameIdentifier, "johndoe@example.com"),
        new Claim(ClaimTypes.Role, "Administrator"),
    , "Custom"),
    NotBefore = DateTime.Now,
    SigningCredentials = signingCredentials,
    Issuer = "self",
    IssuedAt = DateTime.Now,
    Expires = DateTime.Now.AddHours(3),
    Audience = "http://my.website.com"
;

var tokenHandler = new JwtSecurityTokenHandler();
var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);
var signedAndEncodedToken = tokenHandler.WriteToken(plainToken);

并验证

var validationParameters = new TokenValidationParameters()

     ValidateAudience = true,
     ValidAudience = "http://my.website.com",
     ValidateIssuer = true,
     ValidIssuer = "self",
     ValidateIssuerSigningKey = true,
     IssuerSigningKey = signingKey,
     RequireExpirationTime = true,
     ValidateLifetime = true,
     ClockSkew = TimeSpan.Zero
;
try

    SecurityToken mytoken = new JwtSecurityToken();
    var myTokenHandler = new JwtSecurityTokenHandler();
    var myPrincipal = myTokenHandler.ValidateToken(signedAndEncodedToken, validationParameters, out mytoken);
 catch (Exception ex)

    System.Diagnostics.Debug.WriteLine("Authentication failed");

【讨论】:

【参考方案3】:

我设法达到了完全相同的异常。我通过另一种方式生成密钥来解决这个问题:

RSAParameters keyParams;
using (var rsa = new RSACryptoServiceProvider(2048))

    try
    
        keyParams = rsa.ExportParameters(true);
    
    finally
    
        rsa.PersistKeyInCsp = false;
    

RsaSecurityKey key = new RsaSecurityKey(keyParams);
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

这是Mark Hughes 撰写的关于token-based authentication on ASP.NET 5 RC1 的精彩帖子

【讨论】:

谢谢你的回答:)

以上是关于dnx451 RC1 InMemorySymmetricSecurityKey 发生了啥?的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何为 dnx451 和 dnxcore50 引用 HttpClient?

为啥默认的 mvc6 模板针对多个 DNX 版本?

为预处理器指令赋值

dnxcore50可以引用针对.net4.5编译的nuget包吗

AuthorizationHandler异常不通过ExceptionFilter

Service Fabric 中的 .NET Core RC2