标签:strong isnull attribute type help addm toolbar top mat
原文:第二十八节:Asp.Net Core中JWT的几种写法和认证方式
一. 前言
1.说明
本章节重点介绍JWT的利用不同程序集的几种写法及认证方式,然后复习一下JWT的组成。
其他概念参考:https://www.cnblogs.com/yaopengfei/p/10451189.html
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
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 }
封装加密和解密方法
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 }
测试
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
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 }
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); } }
前端页面测试代码
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 });
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
!
第二十八节:Asp.Net Core中JWT的几种写法和认证方式
标签:strong isnull attribute type help addm toolbar top mat
原文地址:https://www.cnblogs.com/lonelyxmas/p/12928275.html