好问题,我上周遇到了同样的问题,最后用同样的JWTAccessToken 解决了。
问题在于,在生成可以在服务器中检索的访问令牌时,将经过身份验证的用户的 UserId 添加为声明。
为访问令牌添加声明
首先将用户的 ID 添加到您的声明列表中。
List<Claim> claims = new List<Claim>();
claims.Add(new Claim("UserId", user.Id.ToString()));
然后生成访问令牌。
SecurityToken token = new JwtSecurityToken(
issuer: {YOUR_ISSUER},
audience: {YOUR_AUDIENCE},
claims: claims,
notBefore: DateTime.UtcNow,
expires: DateTime.UtcNow.AddMinutes(60),
signingCredentials: credentials
);
假设您已经知道如何在生成最终令牌之前执行这些步骤,这些步骤是从您在上面的问题中显示的 oAuth 和 JWT 的能力中扣除的。
从访问令牌中检索声明
要从他们的 access_token 中读取 UserId,让我们创建几个帮助程序/扩展方法来帮助我们从控制器的 RequestContext 中读取 access_token。
public static string GetUserId(this ControllerBase controller)
{
string securityKey = "{YOUR_SECURITY_KEY}";
SymmetricSecurityKey key = new SymmetricSecurityKey(new UTF8Encoding().GetBytes(securityKey));
JwtSecurityTokenHandler token_handler = new JwtSecurityTokenHandler();
var tokenValidationParams = new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateLifetime = false
};
string bearer = controller.HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer", string.Empty).Trim(' ');
List<Claim> claims = token_handler.ValidateToken(bearer, tokenValidationParams, out SecurityToken token).Claims.ToList();
Claim userClaim = claims.FirstOrDefault(x => x.Type == "UserId");
if(userClaim != null)
{
return userClaim.Value;
}
else
{
throw new Exception("Invalid AccessToken. UserId claim not found");
}
}
如何使用
现在让我们使用它在我们的任何控制器中获取 UserId:
[Authorize]
public class ExampleController : Controller
{
public IActionResult Index()
{
string userId = this.GetUserId();
// --> continuing code goes here.
}
}