zoukankan      html  css  js  c++  java
  • 第二十八节:Asp.Net Core中JWT的几种写法和认证方式

    一. 前言

    1.说明

      本章节重点介绍JWT的利用不同程序集的几种写法及认证方式,然后复习一下JWT的组成。

      其他概念参考:https://www.cnblogs.com/yaopengfei/p/10451189.html

      官网:https://jwt.io

    2.JWT组成

      样式:"xxxxxxxxxxxx.xxxxxxxxxxxxx.xxxxxxxxxxxxxxxx"由三部分组成.

    (1).Header头部:{"alg":"HS256","typ":"JWT"}基本组成,也可以自己添加别的内容,然后对最后的内容进行Base64编码.

    (2).Payload负载:iss、sub、aud、exp、nbf、iat、jti基本参数,也可以自己添加别的内容,然后对最后的内容进行Base64编码.

    (3).Signature签名:将Base64后的Header和Payload通过.组合起来,然后利用Hmacsha256+密钥进行加密。

    二. 加解密几种写法

    1. 写法1

      说明:利用规则自己手动封装,安装【NETCore.Encrypt】程序集,利用里面的HMAC加密算法,声明一个expire用于存放过期时间。校验的时候先验证时间是否过期,再验证签名的准确性。

    详细代码见:TestJwt1

     1  #region Base64编码
     2         /// <summary>
     3         /// Base64编码
     4         /// </summary>
     5         /// <param name="text">待编码的文本字符串</param>
     6         /// <returns>编码的文本字符串</returns>
     7         public string Base64UrlEncode(string text)
     8         {
     9             var plainTextBytes = Encoding.UTF8.GetBytes(text);
    10             var base64 = Convert.ToBase64String(plainTextBytes).Replace('+', '-').Replace('/', '_').TrimEnd('=');
    11             return base64;
    12         }
    13         #endregion
    14 
    15         #region Base64解码
    16         /// <summary>
    17         /// Base64解码
    18         /// </summary>
    19         /// <param name="base64UrlStr"></param>
    20         /// <returns></returns>
    21 
    22         public string Base64UrlDecode(string base64UrlStr)
    23         {
    24             base64UrlStr = base64UrlStr.Replace('-', '+').Replace('_', '/');
    25             switch (base64UrlStr.Length % 4)
    26             {
    27                 case 2:
    28                     base64UrlStr += "==";
    29                     break;
    30                 case 3:
    31                     base64UrlStr += "=";
    32                     break;
    33             }
    34             var bytes = Convert.FromBase64String(base64UrlStr);
    35             return Encoding.UTF8.GetString(bytes);
    36         }
    37         #endregion
    Base64编码和解码
     1         /// <summary>
     2         /// 手写JWT算法
     3         /// </summary>
     4         public bool TestJwt1()
     5         {
     6             string secretKey = Configuration["SecretKey"];
     7             //1.加密
     8             //1.1 表头的处理
     9             string headerBase64Url = this.Base64UrlEncode("{"alg":"HS256","typ":"JWT"}");
    10             //1.2 PayLoad的处理
    11             var jwtPayLoad = new
    12             {
    13                 expire = DateTime.Now.AddMinutes(15),
    14                 userId = "00000000001",
    15                 userAccount = "admin"
    16             };
    17             string payloadBase64Url = this.Base64UrlEncode(JsonConvert.SerializeObject(jwtPayLoad));
    18             //1.3 Sign的处理
    19             string sign = $"{headerBase64Url}.{payloadBase64Url}".HMACSHA256(secretKey);
    20             //1.4 最终的jwt字符串
    21             string jwtStr = $"{headerBase64Url}.{payloadBase64Url}.{sign}";
    22 
    23             //2.校验token是否正确
    24             bool result;   //True表示通过,False表示未通过
    25             //2.1. 获取token中的PayLoad中的值,并做过期校验
    26             JwtData myData = JsonConvert.DeserializeObject<JwtData>(this.Base64UrlDecode(jwtStr.Split('.')[1]));  //这一步已经获取到了payload中的值,并进行转换了
    27             var nowTime = DateTime.Now;
    28             if (nowTime > myData.expire)
    29             {
    30                 //表示token过期,校验未通过
    31                 result = false;
    32                 return result;
    33             }
    34             else
    35             {
    36                 //2.2 做准确性校验
    37                 var items = jwtStr.Split('.');
    38                 var oldSign = items[2];
    39                 string newSign = $"{items[0]}.{items[1]}".HMACSHA256(secretKey);
    40                 result = oldSign == newSign;  //true表示检验通过,false表示检验未通过 
    41                 return result;
    42             }
    43         }

    2. 写法2(推荐!)

      说明:使用官方JWT程序集【JWT 5.3.1】,封装加密和解密算法,详见:JWTHelp帮助类.其中加密算法的封装将extraHeaders参数作为一个可空参数,可以根据自己的需要决定是否在Header头中添加额外的参数。

    jwt实体类

    1    public class JwtData
    2     {
    3         public DateTime expire { get; set; }  //代表过期时间
    4 
    5         public string userId { get; set; }
    6 
    7         public string userAccount { get; set; }
    8     }
    JwtData

    封装加密和解密方法

     1    /// <summary>
     2     /// Jwt的加密和解密
     3     /// 注:加密和加密用的是用一个密钥
     4     /// 依赖程序集:【JWT】
     5     /// </summary>
     6     public class JWTHelp
     7     {
     8 
     9         /// <summary>
    10         /// JWT加密算法
    11         /// </summary>
    12         /// <param name="payload">负荷部分,存储使用的信息</param>
    13         /// <param name="secret">密钥</param>
    14         /// <param name="extraHeaders">存放表头额外的信息,不需要的话可以不传</param>
    15         /// <returns></returns>
    16         public static string JWTJiaM(IDictionary<string, object> payload, string secret, IDictionary<string, object> extraHeaders = null)
    17         {
    18             IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
    19             IJsonSerializer serializer = new JsonNetSerializer();
    20             IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
    21             IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
    22             var token = encoder.Encode(payload, secret);
    23             return token;
    24         }
    25 
    26         /// <summary>
    27         /// JWT解密算法
    28         /// </summary>
    29         /// <param name="token">需要解密的token串</param>
    30         /// <param name="secret">密钥</param>
    31         /// <returns></returns>
    32         public static string JWTJieM(string token, string secret)
    33         {
    34             try
    35             {
    36                 IJsonSerializer serializer = new JsonNetSerializer();
    37                 IDateTimeProvider provider = new UtcDateTimeProvider();
    38                 IJwtValidator validator = new JwtValidator(serializer, provider);
    39                 IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
    40                 IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
    41                 var json = decoder.Decode(token, secret, true);
    42                 //校验通过,返回解密后的字符串
    43                 return json;
    44             }
    45             catch (TokenExpiredException)
    46             {
    47                 //表示过期
    48                 return "expired";
    49             }
    50             catch (SignatureVerificationException)
    51             {
    52                 //表示验证不通过
    53                 return "invalid";
    54             }
    55             catch (Exception)
    56             {
    57                 return "error";
    58             }
    59         }
    60 
    61 
    62     }
    JWTHelp

    测试

     1         /// <summary>
     2         /// 利用JWT官方程序集的写法
     3         /// </summary>
     4         public void TestJwt2()
     5         {
     6             string secretKey = Configuration["SecretKey"];
     7 
     8             //1.加密
     9             //1.1 额外的header参数也可以不设置
    10             var extraHeaders = new Dictionary<string, object>
    11                     {
    12                          {"myName", "limaru" },
    13                     };
    14             //过期时间(可以不设置,下面表示签名后 20分钟过期)
    15             double exp = (DateTime.UtcNow.AddMinutes(20) - new DateTime(1970, 1, 1)).TotalSeconds;
    16             //进行组装
    17             var payload = new Dictionary<string, object>
    18                     {
    19                          {"userId", "00000000001" },
    20                          {"userAccount", "admin" },
    21                          {"exp",exp }
    22                     };
    23 
    24             //1.2 进行JWT签名
    25             var token = JWTHelp.JWTJiaM(payload, secretKey, extraHeaders);
    26 
    27             //2. 解密
    28             var result = JWTHelp.JWTJieM(token, secretKey);
    29             //然后在转换一下
    30             JwtData myData = JsonConvert.DeserializeObject<JwtData>(result);
    31 
    32         }

    3. 写法3

      说明:使用Identity家的程序集【System.IdentityModel.Tokens.Jwt】,进行加密和解密,详见:TestJwt3。

    注:下面代码,解密的时候不验证 aud 和 iss, ClockSkew = TimeSpan.Zero  代表校验过期时间的偏移量,即验证过期时间:(expires+该值),该值默认为5min,这里设置为0,表示生成token时的expries即为过期时间 。

     1         public bool TestJwt3()
     2         {
     3             string secretKey = Configuration["SecretKey"];
     4             string token;
     5             //加密
     6             {
     7                 var tokenHandler = new JwtSecurityTokenHandler();
     8                 var key = Encoding.Default.GetBytes(secretKey);
     9                 var tokenDescriptor = new SecurityTokenDescriptor()
    10                 {
    11                     Subject = new ClaimsIdentity(new Claim[] {
    12                          new Claim("userId","00000000001"),
    13                          new Claim("userAccount","admin")
    14                     }),
    15                     Expires = DateTime.UtcNow.AddSeconds(10),
    16                     SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    17                 };
    18                 token = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDescriptor));           //将组装好的格式生成加密后的jwt字符串
    19             }
    20             //解密
    21             bool result;
    22             {
    23                 var tokenHandler = new JwtSecurityTokenHandler();
    24                 var key = Encoding.Default.GetBytes(secretKey);
    25                 var validationParameters = new TokenValidationParameters
    26                 {
    27                     ValidateAudience = false, //表示不验证aud
    28                     ValidateIssuer = false,   //表示不验证iss
    29                     IssuerSigningKey = new SymmetricSecurityKey(key),
    30                     ClockSkew = TimeSpan.Zero   //代表校验过期时间的偏移量,即验证过期时间:(expires+该值),该值默认为5min,这里设置为0,表示生成token时的expries即为过期时间
    31                 };
    32                 SecurityToken validatedToken;   //解密后的对象
    33                 try
    34                 {
    35                     ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
    36                     result = true;
    37                     //获取payload中的数据
    38                     var jwtPayload = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson(); ;
    39                 }
    40                 catch (SecurityTokenExpiredException)
    41                 {
    42                     //表示过期
    43                     result = false;
    44                 }
    45                 catch (SecurityTokenException)
    46                 {
    47                     //表示token错误
    48                     result = false;
    49                 }
    50             }
    51             return result;
    52         } 

    三. 校验的几种方式

    1. 利用过滤器校验

      这里使用override这个方法OnActionExecuting,在action执行之前过滤。

    (1).涉及到几个技术点:

    A.判断aciton是否有某个特性:

      context.ActionDescriptor.EndpointMetadata.Any(x => x.GetType() == typeof(SkipAttribute));

    B.判断是否是ajax请求:

      判断Headers["X-Requested-With"]的值是不是"XMLHttpRequest".

    C.获取传递过来的参数:

      a. ajax放在Header中传递的参数:context.HttpContext.Request.Headers["auth"].ToString();  判空方式:token == "null" || string.IsNullOrEmpty(token)

      b. 通过href=xxx?auth=xx传递的参数:context.HttpContext.Request.Query["auth"].ToString();   判空形式:string.IsNullOrEmpty(token)

    PS:现在有一种Bearer认证, 是这样传递的("Authorization" "Bearer token"), 获取方式同上面的a,但是要拿到token的值,还需要截取一下,详见代码xxxx

    D.过滤器中截断返回的几种形式:

      a.非ajax的截断:直接跳转到某个未授权的页面,如:context.Result = new RedirectResult("/Admin/ErrorIndex?isLogin=noPer");

      b.ajax的截断:

        ①.返回JsonResult,进入ajax中的success回调: context.Result = new JsonResult(new { status = "error", msg = "非法请求,参数已经过期" });

        ②.只返回状态码,进入ajax中的error回调:context.Result = new StatusCodeResult(401); 或 context.HttpContext.Response.StatusCode = 401;

        ③.返回ContentResult,进入ajax的error回调,同时回传错误内容:context.Result = new ContentResult { Content = "没有权限哦", StatusCode = 401 };

      注:推荐上述③,因为可以和正常的请求返回彻底区分开,特别注意过滤器中要加return; 光context.Result不能截断.。

    E.过滤器中传值和action中取值:

      a.传值:context.RouteData.Values.Add("auth", xxxx);

      b.取值:ControllerContext.RouteData.Values["auth"].ToString()

    (2).实战测试

      A:auth认证,指Header中传递参数的时候("auth", token),对于ajax返回JsonResult,校验不通过的时候,进入的是ajax中的success回调.

      B:Bearer认证,说白了就是在Header中传递参数的时候("Authorization", "Bearer " + token),在值的前面加了一个Bearer和空格,然后在解析的时候需要隔离拿出来token值.

    PS:在JwtCheck2中,对于ajax请求验证未通过的时候返回ContextResult,状态码为401,进入ajax的error回调中,非ajax请求和A类似。

     服务端方法:获取token的代码、auth认证接口、Bearer认证接口、没有权限的页面

     1        #region 获取Token
     2         /// <summary>
     3         /// 获取Token
     4         /// </summary>
     5         /// <returns></returns>
     6         public String GetToken()
     7         {
     8             string secretKey = Configuration["SecretKey"];
     9             //1.加密
    10             //1.1 额外的header参数也可以不设置
    11             var extraHeaders = new Dictionary<string, object>
    12                     {
    13                          {"myName", "limaru" },
    14                     };
    15             //过期时间(可以不设置,下面表示签名后 20分钟过期)
    16             double exp = (DateTime.UtcNow.AddMinutes(20) - new DateTime(1970, 1, 1)).TotalSeconds;
    17             //进行组装
    18             var payload = new Dictionary<string, object>
    19                     {
    20                          {"userId", "00000000001" },
    21                          {"userAccount", "admin" },
    22                          {"exp",exp }
    23                     };
    24 
    25             //1.2 进行JWT签名
    26             var token = JWTHelp.JWTJiaM(payload, secretKey, extraHeaders);
    27             return token;
    28         }
    29         #endregion
    30 
    31         #region JwtCheck1校验(auth认证)
    32         [TypeFilter(typeof(JwtCheck1))]
    33         public IActionResult GetMsg1()
    34         {
    35 
    36             var jwtData = JsonConvert.DeserializeObject<JwtData>(ControllerContext.RouteData.Values["auth"].ToString());
    37             return Json(new { status = "ok", msg = jwtData.userId });
    38         }
    39         #endregion
    40 
    41         #region JwtCheck2校验(Bearer认证)
    42         [TypeFilter(typeof(JwtCheck2))]
    43         public IActionResult GetMsg2()
    44         {
    45             var jwtData = JsonConvert.DeserializeObject<JwtData>(ControllerContext.RouteData.Values["auth"].ToString());
    46             return Json(new { status = "ok", msg = jwtData.userId });
    47         }
    48 
    49         #endregion
    View Code

    auth认证过滤器,对于ajax返回的是JsonResult,进入ajax的success

      1     /// <summary>
      2     /// auth认证过滤器,进入ajax的success
      3     /// </summary>
      4     public class JwtCheck1 : ActionFilterAttribute
      5     {
      6 
      7         private IConfiguration _configuration;
      8         public JwtCheck1(IConfiguration configuration)
      9         {
     10             _configuration = configuration;
     11         }
     12 
     13         /// <summary>
     14         /// action执行前执行
     15         /// </summary>
     16         /// <param name="context"></param>
     17         public override void OnActionExecuting(ActionExecutingContext context)
     18         {
     19             //1.判断是否需要校验
     20             var isSkip = context.ActionDescriptor.EndpointMetadata.Any(x => x.GetType() == typeof(SkipAttribute));
     21             if (isSkip == false)
     22             {
     23                 //2. 判断是什么请求(ajax or 非ajax)
     24                 var actionContext = context.HttpContext;
     25                 if (IsAjaxRequest(actionContext.Request))
     26                 {
     27                     //表示是ajax
     28                     var token = context.HttpContext.Request.Headers["auth"].ToString();    //ajax请求传过来
     29                     if (token == "null" || string.IsNullOrEmpty(token))
     30                     {
     31                         context.Result = new JsonResult(new { status = "error", msg = "非法请求,参数为空" });
     32                         return;
     33                     }
     34                     //校验auth的正确性
     35                     var result = JWTHelp.JWTJieM(token, _configuration["SecretKey"]);
     36                     if (result == "expired")
     37                     {
     38                         context.Result = new JsonResult(new { status = "error", msg = "非法请求,参数已经过期" });
     39                         return;
     40                     }
     41                     else if (result == "invalid")
     42                     {
     43                         context.Result = new JsonResult(new { status = "error", msg = "非法请求,未通过校验" });
     44                         return;
     45                     }
     46                     else if (result == "error")
     47                     {
     48                         context.Result = new JsonResult(new { status = "error", msg = "非法请求,未通过校验" });
     49                         return;
     50                     }
     51                     else
     52                     {
     53                         //表示校验通过,用于向控制器中传值
     54                         context.RouteData.Values.Add("auth", result);
     55                     }
     56 
     57                 }
     58                 else
     59                 {
     60                     //表示是非ajax请求,则auth拼接在参数中传过来
     61                     var token = actionContext.Request.Query["auth"].ToString();
     62                     if (token == "null" || string.IsNullOrEmpty(token))
     63                     {
     64                         context.Result = new RedirectResult("/Home/NoPerIndex?reason=null");
     65                         return;
     66                     }
     67                     //校验auth的正确性
     68                     var result = JWTHelp.JWTJieM(token, _configuration["SecretKey"]);
     69                     if (result == "expired")
     70                     {
     71                         context.Result = new RedirectResult("/Home/NoPerIndex?reason=expired");
     72                         return;
     73                     }
     74                     else if (result == "invalid")
     75                     {
     76                         context.Result = new RedirectResult("/Home/NoPerIndex?reason=invalid");
     77                         return;
     78                     }
     79                     else if (result == "error")
     80                     {
     81                         context.Result = new RedirectResult("/Home/NoPerIndex?reason=error");
     82                         return;
     83                     }
     84                     else
     85                     {
     86                         //表示校验通过,用于向控制器中传值
     87                         context.RouteData.Values.Add("auth", result);
     88                     }
     89                 }
     90             }
     91 
     92         }
     93 
     94         /// <summary>
     95         /// 判断该请求是否是ajax请求
     96         /// </summary>
     97         /// <param name="request"></param>
     98         /// <returns></returns>
     99         private bool IsAjaxRequest(HttpRequest request)
    100         {
    101             string header = request.Headers["X-Requested-With"];
    102             return "XMLHttpRequest".Equals(header);
    103         }
    104     }
    View Code

    Bearer认证过滤器,对于ajax返回的是ContentResult,进入的是ajax的error

        /// <summary>
        /// Bearer认证,返回ajax中的error
        /// </summary>
        public class JwtCheck2 : ActionFilterAttribute
        {
    
            private IConfiguration _configuration;
            public JwtCheck2(IConfiguration configuration)
            {
                _configuration = configuration;
            }
    
            /// <summary>
            /// action执行前执行
            /// </summary>
            /// <param name="context"></param>
            public override void OnActionExecuting(ActionExecutingContext context)
            {
                //1.判断是否需要校验
                var isSkip = context.ActionDescriptor.EndpointMetadata.Any(x => x.GetType() == typeof(SkipAttribute));
                if (isSkip == false)
                {
                    //2. 判断是什么请求(ajax or 非ajax)
                    var actionContext = context.HttpContext;
                    if (IsAjaxRequest(actionContext.Request))
                    {
                        //表示是ajax
                        var token = context.HttpContext.Request.Headers["Authorization"].ToString();    //ajax请求传过来
                        string pattern = "^Bearer (.*?)$";
                        if (!Regex.IsMatch(token, pattern))
                        {
                            context.Result = new ContentResult { StatusCode = 401, Content = "token格式不对!格式为:Bearer {token}" };
                            return;
                        }
                        token = Regex.Match(token, pattern).Groups[1]?.ToString();
                        if (token == "null" || string.IsNullOrEmpty(token))
                        {
                            context.Result = new ContentResult { StatusCode = 401, Content = "token不能为空" };
                            return;
                        }
                        //校验auth的正确性
                        var result = JWTHelp.JWTJieM(token, _configuration["SecretKey"]);
                        if (result == "expired")
                        {
                            context.Result = new ContentResult { StatusCode = 401, Content = "expired" };
                            return;
                        }
                        else if (result == "invalid")
                        {
                            context.Result = new ContentResult { StatusCode = 401, Content = "invalid" };
                            return;
                        }
                        else if (result == "error")
                        {
                            context.Result = new ContentResult { StatusCode = 401, Content = "error" };
                            return;
                        }
                        else
                        {
                            //表示校验通过,用于向控制器中传值
                            context.RouteData.Values.Add("auth", result);
                        }
    
                    }
                    else
                    {
                        //表示是非ajax请求,则auth拼接在参数中传过来
                        var token = actionContext.Request.Query["Authorization"].ToString();
                        if (token == "null" || string.IsNullOrEmpty(token))
                        {
                            context.Result = new RedirectResult("/Home/NoPerIndex?reason=null");
                            return;
                        }
                        string pattern = "^Bearer (.*?)$";
                        if (!Regex.IsMatch(token, pattern))
                        {
                            context.Result = new RedirectResult("/Home/NoPerIndex?reason=token格式不对!格式为:Bearer {token}");
                            return;
                        }
                        token = Regex.Match(token, pattern).Groups[1]?.ToString();
                        if (token == "null" || string.IsNullOrEmpty(token))
                        {
                            context.Result = new RedirectResult("/Home/NoPerIndex?reason=token不能为空");
                            return;
                        }
                        //校验auth的正确性
                        var result = JWTHelp.JWTJieM(token, _configuration["SecretKey"]);
                        if (result == "expired")
                        {
                            context.Result = new RedirectResult("/Home/NoPerIndex?reason=expired");
                            return;
                        }
                        else if (result == "invalid")
                        {
                            context.Result = new RedirectResult("/Home/NoPerIndex?reason=invalid");
                            return;
                        }
                        else if (result == "error")
                        {
                            context.Result = new RedirectResult("/Home/NoPerIndex?reason=error");
                            return;
                        }
                        else
                        {
                            //表示校验通过,用于向控制器中传值
                            context.RouteData.Values.Add("auth", result);
                        }
                    }
                }
    
            }
    
    
            /// <summary>
            /// 判断该请求是否是ajax请求
            /// </summary>
            /// <param name="request"></param>
            /// <returns></returns>
            private bool IsAjaxRequest(HttpRequest request)
            {
                string header = request.Headers["X-Requested-With"];
                return "XMLHttpRequest".Equals(header);
            }
        }
    View Code

    前端页面测试代码

     1           //获取token
     2             $("#j_btn1").click(function () {
     3                 $.ajax({
     4                     url: "/Home/GetToken",
     5                     type: "Get",
     6                     data: {},
     7                     datatype: "json",
     8                     success: function (data) {
     9                         console.log(data);
    10                         window.localStorage.setItem("token", data);
    11                         alert("获取成功");
    12                     }
    13                 });
    14             });
    15             //2.测试校验(auth验证-ajax)
    16             $("#j_btn2").click(function () {
    17                 var token = window.localStorage.getItem("token");
    18                 $.ajax({
    19                     url: "/Home/GetMsg1",
    20                     type: "Get",
    21                     data: {},
    22                     datatype: "json",
    23                     //设置header的方式1
    24                     //headers: { "auth": token },
    25                     //设置header的方式2
    26                     beforeSend: function (xhr) {
    27                         xhr.setRequestHeader("auth", token);
    28                     },
    29                     success: function (data) {
    30                         if (data.status == "ok") {
    31                             alert(data.msg);
    32                         } else {
    33                             alert(data.msg);
    34                         }
    35                     }
    36                 });
    37             });
    38 
    39             //3.测试校验(auth验证-非ajax)
    40             $("#j_btn3").click(function () {
    41                 var token = window.localStorage.getItem("token");
    42                 window.location.href = "/Home/GetMsg1?auth=" + token;
    43             });
    44 
    45             //4.测试校验(Bearer验证-ajax)
    46             $("#j_btn4").click(function () {
    47                 var token = window.localStorage.getItem("token");
    48                 $.ajax({
    49                     url: "/Home/GetMsg2",
    50                     type: "Get",
    51                     data: {},
    52                     datatype: "json",
    53                     //设置header的方式1
    54                     //headers: { "auth": token },
    55                     //设置header的方式2
    56                     beforeSend: function (xhr) {
    57                         xhr.setRequestHeader("Authorization", "Bearer " + token);
    58                     },
    59                     success: function (data) {
    60                         if (data.status == "ok") {
    61                             alert(data.msg);
    62                         } else {
    63                             alert(data.msg);
    64                         }
    65                     },
    66                     //当安全校验未通过的时候进入这里
    67                     error: function (xhr) {
    68                         if (xhr.status == 401) {
    69                             console.log(xhr.responseText);
    70                             alert(xhr.responseText)
    71                         }
    72                     }
    73                 });
    74             });
    75 
    76             //5.测试校验(Bearer验证-非ajax)
    77             $("#j_btn5").click(function () {
    78                 var token = window.localStorage.getItem("token");
    79                 window.location.href = "/Home/GetMsg2?Authorization=Bearer " + token;
    80             });
    View Code

    2. 利用中间件校验

      认证依赖程序集:【Microsoft.AspNetCore.Authentication.JwtBearer】,在ConfigureService进行jwt的注册,然后在Configure中使用 app.UseAuthentication();进行全局认证。

    服务端方法:获取token的代码、认证接口

     1         /// <summary>
     2         /// 获取Token
     3         /// </summary>
     4         /// <returns></returns>
     5         public String GetToken2()
     6         {
     7             string secretKey = Configuration["SecretKey"];
     8             string token;
     9             //加密
    10             {
    11                 var tokenHandler = new JwtSecurityTokenHandler();
    12                 var key = Encoding.Default.GetBytes(secretKey);
    13                 var tokenDescriptor = new SecurityTokenDescriptor()
    14                 {
    15                     Subject = new ClaimsIdentity(new Claim[] {
    16                          new Claim("userId","00000000001"),
    17                          new Claim("userAccount","admin")
    18                     }),
    19                     Expires = DateTime.UtcNow.AddSeconds(10),
    20                     SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    21                 };
    22                 token = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDescriptor));           //将组装好的格式生成加密后的jwt字符串
    23             }
    24             return token;
    25 
    26         }
    27         /// <summary>
    28         /// 获取信息
    29         /// </summary>
    30         /// <returns></returns>
    31         [Authorize]
    32         public string GetMsg3()
    33         {
    34             return "ok";
    35         } 

    中间件代码

     1   public void ConfigureServices(IServiceCollection services)
     2         {
     3 
     4             //注册jwt校验
     5             services.AddAuthentication("Bearer").AddJwtBearer(options =>
     6             {
     7                 options.TokenValidationParameters = new TokenValidationParameters
     8                 {
     9                     ValidateIssuer = false,//是否验证Issuer
    10                     ValidateAudience = false,//是否验证Audience
    11                     ClockSkew = TimeSpan.Zero,//校验时间是否过期时,设置的时钟偏移量(默认是5min,这里设置为0,即用的是产生token时设置的国企时间)
    12                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(Configuration["SecretKey"])),//拿到SecurityKey
    13                 };
    14             });
    15 
    16             services.AddControllersWithViews();
    17         }

     前端代码:

     1          //下面是基于【System.IdentityModel.Tokens.Jwt】的jwt校验
     2             $("#j_btn6").click(function () {
     3                 $.ajax({
     4                     url: "/Home/GetToken2",
     5                     type: "Get",
     6                     data: {},
     7                     datatype: "json",
     8                     success: function (data) {
     9                         console.log(data);
    10                         window.localStorage.setItem("token", data);
    11                         alert("获取成功");
    12                     }
    13                 });
    14             });
    15             $("#j_btn7").click(function () {
    16                 var token = window.localStorage.getItem("token");
    17                 $.ajax({
    18                     url: "/Home/GetMsg3",
    19                     type: "Get",
    20                     data: {},
    21                     datatype: "json",
    22                     //设置header的方式1
    23                     headers: {
    24                         "Authorization": "Bearer " + token,
    25                     },
    26                     //设置header的方式2
    27                     //beforeSend: function (xhr) {
    28                     //    xhr.setRequestHeader("Authorization", "Bearer " + token);
    29                     //},
    30                     success: function (data) {
    31                         alert(data);
    32                     },
    33                     //当安全校验未通过的时候进入这里
    34                     error: function (xhr) {
    35                         if (xhr.status == 401) {
    36                             alert("校验未通过");
    37                         }
    38                     }
    39                 });
    40             });

    其它博客:https://www.cnblogs.com/CreateMyself/p/11123023.html

    参考: https://www.jianshu.com/p/be936f1fba95

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    edgecore
    十问 Linux 虚拟内存管理 (glibc)
    Covered Path
    Journey Planning
    K for the Price of One
    Candies!
    2种方式解决nginx负载下的Web API站点里swagger无法使用
    分布式环境下的数据一致性问题的方案讨论
    static,你还敢用吗?
    分离EF connectionString里的db连接串
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/12162507.html
Copyright © 2011-2022 走看看