AHA*_*AHA 5 asp.net authentication authorization lifetime jwt
我在ASP上创建自己的自定义身份验证.Net Mobile部署在Azure上.我使用JWT令牌.以下是我生成新令牌的方法(claimType = email):
public static string GetSecurityToken(String email)
{
var symmetricKey = Convert.FromBase64String(signingKey);
var tokenHandler = new JwtSecurityTokenHandler();
var now = DateTime.UtcNow;
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Email, email)
}),
NotBefore = now,
Expires = now.AddYears(10),
Issuer = issuer,
Audience = audience,
IssuedAt = now,
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(symmetricKey),
SecurityAlgorithms.HmacSha256Signature),
};
var stoken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(stoken);
return token;
}
Run Code Online (Sandbox Code Playgroud)
令牌被发送到客户端并存储.但是当我尝试基于其令牌授权消息时,我收到错误:
终身验证失败.令牌缺少过期时间.
这是我尝试验证令牌的方式:
public static ClaimsPrincipal GetPrincipal(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken;
if (jwtToken == null)
return null;
var symmetricKey = Convert.FromBase64String(signingKey);
Debug.WriteLine(String.Format("JWTManager > GetPrincipal > Validating Token: {0}", token));
foreach (Claim claim in jwtToken.Claims)
{
Debug.WriteLine(String.Format("JWTManager > GetPrincipal > Claims: {0}", claim.ToString()));
}
var validationParameters = new TokenValidationParameters()
{
//RequireExpirationTime = true,
//ValidateLifetime = true,
ValidateIssuer = true,
ValidateAudience = true,
IssuerSigningKey = new SymmetricSecurityKey(symmetricKey),
};
SecurityToken securityToken;
var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
if (principal != null)
Debug.WriteLine(String.Format("JWTManager > GetPrincipal > Principal: {0}", principal));
return principal;
}
catch (SecurityTokenException ex)
{
Debug.WriteLine(String.Format("JWTManager > GetPrincipal: {0}", ex.Message));
return null;
}
catch (Exception ex)
{
Debug.WriteLine(String.Format("JWTManager > GetPrincipal: {0}", ex.Message));
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
执行时抛出异常tokenHandler.ValidateToken并返回null principal.
我的假设是,我可能没有正确设置Expires和Issuers属性,并且TokenHanlder无法验证它们.但是,当我检查jwtToken时,所有声明都已正确设置.
这是完整的调试输出:
JWTManager> GetPrincipal>声明:电子邮件:testEmail@email.com
JWTManager> GetPrincipal>声明:nbf:1494752301
JWTManager> GetPrincipal> Claims:exp:33051661101
JWTManager> GetPrincipal>声明:iat:1494752301
JWTManager> GetPrincipal>声明:iss:MASKED
JWTManager> GetPrincipal>声明:aud:MAKSED
JWTManager> GetPrincipal:IDX10225:生命周期验证失败.令牌缺少过期时间.应用:Tokentype:
Awa*_*Teh 13
@aha,看起来您通过将到期日期时间缩短到未来一年来解决您的问题.哪个有效,但是如果你想了解它之前失败的基础架构原因(并且因此在你自己的代码中进行适当的架构更改),你可以在这里阅读这篇SO帖子:https://stackoverflow.com/a/ 46654832/1222775.
底线是针对Microsoft owin中间件验证的JWT的到期日期具有上限2147483647(也恰好是Int32.MaxValue),并且转换为:Tue, 19 Jan 2038 03:14:07 GMT
在您的SO问题中,您发布的调试输出显示您使用的"exp"声明值,其值33051661101转换为:Wednesday, May 14, 3017 8:58:21 AM它超过Microsoft的exp值的上限差不多80年:).
我希望微软能尽快解决这个问题,但是对于遇到类似问题的人来说,同时不要发出太长时间的令牌,或者至少不要让它超过Tue,2038年1月19日@ 03:14 :07 GMT :).
按照此处的建议,我通过从使用切换来解决了问题
System.IdentityModel.Tokens.Jwt.TokenHandler.CreateToken(SecurityTokenDescriptor)
到
new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(JwtHeader, JwtPayload)。
并将有效负载定义如下:
DateTime centuryBegin = new DateTime(1970, 1, 1);
var exp = new TimeSpan(DateTime.Now.AddYears(1).Ticks - centuryBegin.Ticks).TotalSeconds;
var now = new TimeSpan(DateTime.Now.Ticks - centuryBegin.Ticks).TotalSeconds;
var payload = new System.IdentityModel.Tokens.Jwt.JwtPayload
{
{"iss", issuer},
{"aud", audience},
{"iat", (long)now},
{"exp", (long)exp}
};
Run Code Online (Sandbox Code Playgroud)
因此,我最终没有使用 SecurityTokenDescriptor 类,因为它希望将 DateTime 对象分配给Expirs和IssuedAt或Lifetime属性(取决于它是否位于Microsoft.IdentityModel.Tokens或System.IdentityModel.Tokens命名空间中)。
我无意使用 SecurityTokenDescriptor;但是,我找不到有关如何使用 SecurityTokenDescriptor 的解决方案,并且仍然为“exp”字段设置正确的值。
| 归档时间: |
|
| 查看次数: |
6550 次 |
| 最近记录: |