• NetCore3.1 Json web token 中间件


    十年河东,十年河西,莫欺少年穷

    学无止境,精益求精

    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 会打印当前请求人的基本信息,也就是:陈卧龙  在苏州 喜欢美女  这些

    @天才卧龙的博客

  • 相关阅读:
    2015.05.12:json的常用处理方式
    好菜都得花功夫做
    网站从 IIS6 迁移至 IIS7 后的通配符脚本映射权限配置不当可能导致403错误
    ELearning是学习系统而不是教育系统
    空难与软件开发(一)
    “模态”对话框和“后退”按钮
    闭包解析(Fun with closure)
    关于CultureInfo的两个问题
    从来就不可能精通:关于Boxing
    Windows RT 应用程序开发介绍培训的讲义
  • 原文地址:https://www.cnblogs.com/chenwolong/p/16444022.html
Copyright © 2020-2023  润新知