十年河东,十年河西,莫欺少年穷 学无止境,精益求精 1、项目中引入jwt 2、创建token的实例代码如下: 2.1、所需的实体类 /// summary /// POCO类,用来存储签发或者验证jwt时用到的信息
十年河东,十年河西,莫欺少年穷
学无止境,精益求精
1、项目中引入jwt
2、创建token的实例代码如下:
2.1、所需的实体类
/// <summary> /// POCO类,用来存储签发或者验证jwt时用到的信息 /// </summary> public class TokenOptions { public static string Secret = "chenwolong_love_woman_2022";//私钥 至少16个字符 public static string Issuer = "webapi.cn"; public static string Audience = "WebApi"; public static int AccessExpiration = 180;//过期时间 }
2.2、创建Token
public dynamic UserLogin(string uname, string upwd) { var userinfo = new { uname = "陈卧龙", sex = "男", age = 30, userrole = new List<string>() { "admin", "staff" }, city = "苏州", love = "美女" }; var expiresTime = DateTime.Now.AddMinutes(TokenOptions.AccessExpiration); var claims = new[] { new Claim(ClaimTypes.Name,uname), new Claim(ClaimTypes.Role,ClaimTypes.Role ), // new Claim(ClaimTypes.Actor,"wuan"), new Claim(ClaimTypes.Country,"China"), new Claim(ClaimTypes.Expired,"China"), new Claim(ClaimTypes.UserData,JsonConvert.SerializeObject(userinfo)) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TokenOptions.Secret)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var jwtToken = new JwtSecurityToken(TokenOptions.Issuer, TokenOptions.Audience, claims, expires: expiresTime, signingCredentials: credentials); var token = new JwtSecurityTokenHandler().WriteToken(jwtToken); //加上 "Bearer " 是为了兼容swagger return new { token = "Bearer "+ token, expiresTime = expiresTime.ToString("yyyy-MM-dd HH:mm:ss") }; }
3、jwt 中间件
3.1、所需的实体
public class CurrentUser { public string uname { get; set; } public string sex { get; set; } public int age { get; set; } public List<string> userrole { get; set; } = new List<string>(); public string city { get; set; } public string love { get; set; } }
仔细看这个实体类,和我们创建token时定义的匿名变量是一致的
3.2、中间件的编写
using Microsoft.AspNetCore.Http; using Microsoft.IdentityModel.Tokens; using System; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using wuanModel; namespace wuanIotApi.Middlewares { public class JwtMiddlewares { private readonly RequestDelegate _next; public JwtMiddlewares(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { context.Request.Headers.TryGetValue("Authorization", out var apiKeyHeaderValues); if (apiKeyHeaderValues.Count > 0) { //这里是为了兼容swagger var token = apiKeyHeaderValues.FirstOrDefault().Replace("Bearer ",""); AttachUserToContext(context, token); } await _next.Invoke(context); } private void AttachUserToContext(HttpContext context, string token) { try { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.UTF8.GetBytes(TokenOptions.Secret); //获取到用于生成token的加密key tokenHandler.ValidateToken(token, new TokenValidationParameters { ValidateIssuerSigningKey = true, //是否验证Key SecurityKey IssuerSigningKey = new SymmetricSecurityKey(key), //拿到SecurityKey ValidateIssuer = false, //是否验证Issuer ValidateAudience = false, //是否验证Audience ValidateLifetime = true, //是否验证Token的失效时间 }, out SecurityToken validatedToken); var jwtToken = (JwtSecurityToken)validatedToken; //调试得知,ValidTo时间时区和北京时间相差8小时,通过这个时间,判断Token是否过期 var ValidTo = jwtToken.ValidTo.AddHours(8); if (ValidTo < DateTime.Now) { return; } var userdata = jwtToken.Claims.Where(A => A.Type.Contains("userdata")).ToList().FirstOrDefault().Value; //写入认证信息,方便业务类使用 var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim("userdata", userdata) }); Thread.CurrentPrincipal = new ClaimsPrincipal(claimsIdentity); //将Token中解析出来的用户信息存入当前请求中 context.Items["userdata"] = Newtonsoft.Json.JsonConvert.DeserializeObject<CurrentUser>(userdata); } catch (Exception ex) { context.Items["userdata"] = null; } } } }
context.Items["userdata"]的使用
4、创建基础控制器
4.1,基础控制器
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Newtonsoft.Json; using wuanCommon; using wuanModel; namespace wuanIotApi.Controllers { [Authorize] [Route("api/V1/[controller]")] [ApiExplorerSettings(GroupName = "V1")] public class BaseController : Controller { public CurrentUser user = new CurrentUser(); public BaseController() { } /// <summary> /// 第2步执行基类构造函数 /// 第3步 执行父类的异步方法 异步方法 似乎可以和OnActionExecuting同时执行 /// </summary> /// <param name="context"></param> /// <param name="next"></param> /// <returns></returns> public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { return base.OnActionExecutionAsync(context, next); } /// <summary> /// 第4步 执行OnActionExecuting方法 /// </summary> /// <param name="context"></param> public override void OnActionExecuting(ActionExecutingContext context) { if (!Request.Headers.TryGetValue("Authorization", out var apiKeyHeaderValues)) { user =null; } else { user = (CurrentUser)this.HttpContext.Items["userdata"]; } } /// <summary> /// 第五步执行基类Action /// 第6步 Aciton执行完毕后 执行 OnActionExecuted /// </summary> /// <param name="context"></param> public override void OnActionExecuted(ActionExecutedContext context) { base.OnActionExecuted(context); } } }
4.2 ,继承自基础控制器的其他webapi控制器
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using wuanInterface; namespace wuanIotApi.Controllers { public class UserController : BaseController { private readonly IUserService service; public UserController(IUserService _service) { this.service = _service; } /// <summary> /// 用户登录 /// </summary> /// <returns></returns> [AllowAnonymous] [HttpPost] [Route("UserLogin")] public IActionResult UserLogin() { var result = service.UserLogin("", ""); return Ok(result); } [HttpPost] [Route("TokenTest")] public IActionResult TokenTest() { return Ok(user); } } }
当带Token请求时,其中 TokenTest 会打印当前请求人的基本信息,也就是:陈卧龙 在苏州 喜欢美女 这些
@天才卧龙的博客
只爱少妇