浅谈ASP.NET Core 中jwt授权认证的流程原理

2020-03-19 16:03:24王振洲

解析出的 Token 是一个 ClaimsPrincipal 对象,将此对象给 context.User 赋值,然后在 API 中可以使用 User 实例来获取用户的信息。

在中间件中,使用下面的代码可以获取客户端请求的 Token 解析。

context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, JwtBearerDefaults.AuthenticationScheme);

那么,我们如何手工从原生的 Http 请求中,解析出来呢?且看我慢慢来分解步骤。

首先创建一个 TestMiddleware 文件,作为中间件使用。

 public class TestMiddleware
 {
  private readonly RequestDelegate _next;
  jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
  public TestMiddleware(RequestDelegate next)
  {
   _next = next;
  }
  public async Task Invoke(HttpContext context)
  {
   if (context == null)
   {
    throw new ArgumentNullException(nameof(context));
   }

   // 我们写代码的区域


   // 我们写代码的区域
   await _next(context);
  }
 }

2.1.1 从 Http 中获取 Token

下面代码可以中 http 请求中,取得头部的 Token 。

当然,客户端可能没有携带 Token,可能获取结果为 null ,自己加个判断。

贴到代码区域。

 string tokenStr = context.Request.Headers["Authorization"].ToString();

Header 的 Authorization 键,是由 Breaer {Token}组成的字符串。

2.1.2 判断是否为有效令牌

拿到 Token 后,还需要判断这个 Token 是否有效。

因为 Authorization 是由 Breaer {Token}组成,所以我们需要去掉前面的 Brear 才能获取 Token。

 /// <summary>
  /// Token是否是符合要求的标准 Json Web 令牌
  /// </summary>
  /// <param name="tokenStr"></param>
  /// <returns></returns>
  public bool IsCanReadToken(ref string tokenStr)
  {
   if (string.IsNullOrWhiteSpace(tokenStr) || tokenStr.Length < 7)
    return false;
   if (!tokenStr.Substring(0, 6).Equals(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme))
    return false;
   tokenStr = tokenStr.Substring(7);
   bool isCan = jwtSecurityTokenHandler.CanReadToken(tokenStr);

   return isCan;
  }

获得 Token 后,通过 JwtSecurityTokenHandler.CanReadToken(tokenStr); 来判断 Token 是否符合协议规范。

将下面判断贴到代码区域。

if (!IsCanReadToken(ref tokenStr))
    return ;

2.1.3 解析 Token

下面代码可以将 Header 的 Authorization 内容转为 JwtSecurityToken 对象。

(截取字符串的方式很多种,喜欢哪个就哪个。。。)

 /// <summary>
  /// 从Token解密出JwtSecurityToken,JwtSecurityToken : SecurityToken
  /// </summary>
  /// <param name="tokenStr"></param>
  /// <returns></returns>
  public JwtSecurityToken GetJwtSecurityToken(string tokenStr)
  {
   var jwt = jwtSecurityTokenHandler.ReadJwtToken(tokenStr);
   return jwt;
  }