首页 > 其他分享 >.NET CORE 6 集成认证机制JWT

.NET CORE 6 集成认证机制JWT

时间:2023-05-22 16:44:05浏览次数:44  
标签:CORE string JWT System using new NET public

一:什么是JWT?

JWT (全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

 

二:JWT数据结构

头部

JWT 第一部分是头部分,它是一个描述 JWT 元数据的 Json 对象

    {
    "alg": "HS256",
    "typ": "JWT"
    }

alg 属性表示签名使用的算法,默认为 HMAC SHA256(写为HS256),typ 属性表示令牌的类型,JWT 令牌统一写为JWT。

最后,使用 Base64 URL 算法将上述 JSON 对象转换为字符串保存。

 

载荷

JWT 第二部分是 Payload,也是一个 Json 对象,除了包含需要传递的数据,还有七个默认的字段供选择。

  • iss (issuer):签发人/发行人

  • sub (subject):主题

  • aud (audience):用户

  • exp (expiration time):过期时间

  • nbf (Not Before):生效时间,在此之前是无效的

  • iat (Issued At):签发时间

  • jti (JWT ID):用于标识该 JWT

也可自定义字段

{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

签名

JWT第三部分是签名(Signature)

签名部分是对前两部分(头部,载荷)的签名,防止数据篡改。

按下列步骤生成:
1、先指定密钥(secret)
2、把头部(header)和载荷(payload)信息分别base64转换
3、使用头部(header)指定的算法加密
最终,签名(signature) = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用 "点"( . )分隔

 

三:JWT特点

  • JWT更加简洁
  • JWT适合一次性验证
  • JWT适合无状态认证
  • 相对于数据库Session查询更加省时
  • JWT默认不加密

JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的令牌的权限,一旦JWT签发,在有效期内将会一直有效

JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。

为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。

 

 

四:JWT的使用

 

项目引用包:Microsoft.AspNetCore.Authentication.JwtBearer

 

 

配置文件中添加

  "JWTConfig": {
    "Secret": "abcdefghijklmnop", //密钥
    "Issuer": "Sw163.API", //颁发者
    "Audience": "Jst", //使用者
    "AccessExpiration": 30, //过期时间
    "RefreshExpiration": 60 //刷新过期时间
  },

在Token中添加JwtHelper类

 JwtHelper

using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;

namespace SW163.Token.Model
{
    /// <summary>
    /// 令牌
    /// </summary>
    public class JwtUserInfo
    {
        /// <summary>
        /// Id
        /// </summary>
        public long Uid { get; set; }
        /// <summary>
        /// 角色
        /// </summary>
        public string Role { get; set; }
        /// <summary>
        /// 职能
        /// </summary>
        public string Work { get; set; }

    }


/// <summary>
/// JWT操作帮助类
/// </summary>
public class JwtHelper
    {
        /// <summary>
        /// 颁发JWT
        /// </summary>
        /// <param name="tokenModel">当前颁发对象的用户信息</param>
        /// <returns>JWT字符串</returns>
        public static string IssueJwt(JwtUserInfo jwtUserInfo)
        {
            #region 【Step1-从配置文件中获取生成JWT所需要的数据】
            string iss = Appsettings.GetVal(new string[] { "JWTConfig", "Issuer" });//颁发者
            string aud = Appsettings.GetVal(new string[] { "JWTConfig", "Audience" });//使用者
            string secret = Appsettings.GetVal(new string[] { "JWTConfig", "Secret" }); //密钥
            #endregion

            #region 【Step2-通过Claim创建JWT中的Payload(载荷)信息】

            var claimsIdentity = new List<Claim>
                {
                 new Claim(JwtRegisteredClaimNames.Jti, jwtUserInfo.Uid.ToString()), //JWT ID
                new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),//JWT的发布时间
                new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(600)).ToUnixTimeSeconds()}"),//JWT到期时间
                new Claim(JwtRegisteredClaimNames.Iss,iss), //颁发者
                new Claim(JwtRegisteredClaimNames.Aud,aud)//使用者
               };

            //添加用户的角色信息(非必须,可添加多个)
            var claimRoleList = jwtUserInfo.Role.Split(',').Select(role => new Claim(ClaimTypes.Role, role)).ToList();
            claimsIdentity.AddRange(claimRoleList);
            #endregion

            #region 【Step3-签名对象】

            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); //创建密钥对象
            var sigCreds = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); //创建密钥签名对象

            #endregion

            #region 【Step5-将JWT相关信息封装成对象】
            var jwt = new JwtSecurityToken(
              issuer: iss,
              claims: claimsIdentity,
              signingCredentials: sigCreds);
            #endregion

            #region 【Step6-将JWT信息对象生成字符串形式】
            var jwtHandler = new JwtSecurityTokenHandler();
            string token = jwtHandler.WriteToken(jwt);
            #endregion

            return token;
        } // END IssueJwt()

        /// <summary>
        /// 将JWT加密的字符串进行解析
        /// </summary>
        /// <param name="jwtStr">JWT加密的字符</param>
        /// <returns>JWT中的用户信息</returns>
        public static JwtUserInfo SerializeJwtStr(string jwtStr)
        {
            JwtUserInfo jwtUserInfo = new JwtUserInfo();
            var jwtHandler = new JwtSecurityTokenHandler();

            if (!string.IsNullOrEmpty(jwtStr) && jwtHandler.CanReadToken(jwtStr))
            {
                //将JWT字符读取到JWT对象
                JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);

                //获取JWT中的用户信息
                jwtUserInfo.Uid = Convert.ToInt64(jwtToken.Id);
                object role;
                jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role); //获取角色信息
                jwtUserInfo.Role = role == null ? "" : role.ToString();
            }
            return jwtUserInfo;
        } //END SerializeJwt()

    }

}

Appsettings.cs

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SW163.Token
{
    /// <summary>
    /// 用于帮助读取appsettings.json中的系统配置参数
    /// </summary>
    public class Appsettings
    {
        static IConfiguration Configuration { get; set; }

        public Appsettings(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        /// <summary>
        /// 获取用appsettings.json某个字段下的值
        /// </summary>
        /// <param name="sections">获取值所在的字段(基于JSON层次结构,某个值会存在于多个层级的字段中)</param>
        /// <returns>JSON字段的值</returns>
        public static string GetVal(params string[] sections)
        {
            try
            {
                if (sections.Any())
                {
                    string key = string.Join(":", sections);
                    return Configuration[key];
                }
            }
            catch (Exception) { }

            return string.Empty;
        } // END GetVal()

        /// <summary>
        /// 获取用appsettings.json某个字段下值(值是一个组数)
        /// </summary>
        /// <param name="sections">获取值所在的字段(基于JSON层次结构,某个值会存在于多个层级的字段中)</param>
        /// <returns>JSON字段的多个值(集合)</returns>
        public static List<T> GetValues<T>(params string[] sections)
        {
            List<T> list = new List<T>();
            Configuration.Bind(string.Join(":", sections), list);
            return list;
        } // END GetValues()
    }
}

Startup添加JWT认证的相关配置

ConfigureServices中添加

  services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "JST API", Version = "v1" });
                #region 
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                var xmlPath = Path.Combine(basePath, "WebApi.xml");
                c.IncludeXmlComments(xmlPath, true);
                #endregion

                #region Token绑定到ConfigureServices
                // 开启小锁
                c.OperationFilter<AddResponseHeadersFilter>();
                c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
                // 在header中添加token,传递到后台
                c.OperationFilter<SecurityRequirementsOperationFilter>();

                c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                {
                    Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
                    Name = "Authorization",//jwt默认的参数名称
                    In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                    Type = SecuritySchemeType.ApiKey
                });
                #endregion
            });

            services.AddSingleton(new Appsettings(Configuration)); //将Appsettings对象以单例模式进行注入

Configure中添加

            //先开启认证
            app.UseAuthentication();

            //在开启授权
            app.UseAuthorization();

 

创建授权控制器验证

 

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SW163.Domain;
using SW163.Domain.IRepository;
using SW163.Token.Model;
using SW163.WebApi.Controllers;
using SW163.Infrastructure;
using System.Threading.Tasks;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using System;
using System.ComponentModel;

namespace SW163.WebApi.Api.System
{
    /// <summary>
    /// 获取jwt令牌
    /// </summary>
    [Route("api/[controller]")]
    [Description("账户信息")]
    [ApiController]
    public class AccountController : ControllerBase
    {

        public AccountController(IAdministratorRepository administratorRepository)
        {

            AdministratorRepository = administratorRepository;
        }

        public IAdministratorRepository AdministratorRepository { get; }


        [HttpGet,Route("GetJwtStr")]
        public async Task<object> GetJwtStr(string UserName, string PassWord)
        {
            //验证登录有效性。。。。
            var pwd =DESEncrypt.Encrypt(PassWord);
            var admin = await AdministratorRepository.GetEntityAsync(x => x.UserName == UserName && x.PassWord == pwd);
            if (admin!=null)
            {
                //登陆成功后,基于当前用户生成JWT令牌字符串
                JwtUserInfo jwtUserInfo = new JwtUserInfo { Uid = 1, Role = "Admin,Leader" };
                string jwtStr = JwtHelper.IssueJwt(jwtUserInfo);
                return Ok(new { success = true, token = jwtStr, Id = admin.Id, RoleId = admin.RoleId });
            }
            return NotFound(new { success = false, token = "此账号不存在", Id = 0, RoleId = 0 });
        }

    }
}

 

运行结果

 

 

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxIiwiaWF0IjoiMTY4NDc0NDQzNCIsImV4cCI6IjE2ODQ3NDUwMzQiLCJpc3MiOiJTdzE2My5BUEkiLCJhdWQiOiJKc3QiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOlsiQWRtaW4iLCJMZWFkZXIiXX0.eaQKe4kOdx5p2iSQV_Td_bqmX-vOdh6gb0y7mxPmkXM

 

标签:CORE,string,JWT,System,using,new,NET,public
From: https://www.cnblogs.com/jstblog/p/17421032.html

相关文章

  • Combining Label Propagation and Simple Models Out-performs Graph Neural Networks
    目录概符号说明C&S代码HuangQ.,HeH.,SinghA.,LimS.andBensonA.R.Combininglabelpropagationandsimplemodelsout-performsgraphneuralnetworks.ICLR,2021.概将预测概率作为信号进行传播.符号说明\(G=(V,E)\),图;\(|V|=n\);\(X\in\mathbb{R}......
  • .NET入门相关学习
    2023年05月22日笔记项目信息实体添加新属性①类增加对应属性声明。②快捷键Ctrl+Shift+B生成新应用;或者终端指令dotnetbuild生成新应用。③对应Controller字段增加属性;View视图增加对应部件(Index/Create/Edit);更新 SeedData 类。④PMC中输入指令进行数据库模型迁移:Add-Mi......
  • Kubernetes 初始化容器及静态Pod和Pod调度策略
    初始化容器kubernetes1.3版本引入了initcontainer初始化容器特性。主要用于在启动应用容器(appcontainer)前来启动一个或多个初始化容器,作为应用容器的一个基础。#查看要修改的内核参数[root@kmaster~]#sysctl-a|grepvm.overcommit_ratiovm.overcommit_ratio=50#输......
  • 使用这些.NET代码生成器,开发效率飙升
    在.NET开发过程中,可以使用一些辅助的代码生成器来提高开发效率,之前在.NETFW时代有国产的“动软代码生成器”,现在早已不维护了。下面介绍几种.NET码生成器,供大家参考使用。最后一个代码生产器绝对优秀,推荐使用。T4TextTemplateGenerator:简介:T4是.NET框架提供的一种代码生成......
  • Window权限维持(十):Netsh Helper DLL
    Netsh是Windows实用程序,管理员可以使用它来执行与系统的网络配置有关的任务,并在基于主机的Windows防火墙上进行修改。可以通过使用DLL文件来扩展Netsh功能。此功能使红队可以使用此工具来加载任意DLL,以实现代码执行并因此实现持久性。但是,此技术的实现需要本地管理员级别的特权。可......
  • dotnet平台Http消息处理者工厂
    1前言Microsoft.Extensions.Http是一个设计非常优异的客户端工厂库,其提供了IHttpClientFactory用于创建HttpClient和IHttpMessageHandlerFactory用于创建HttpMessageHandler。遗憾的是这个库目前仅非常试用于客户端,而不太适用于转发端。我们对客户端的定义是一个软件在某种业务......
  • ASP.NET Core 用 Hangfire 实现定时任务周期任务
    前言系统经常会有一些逻辑或任务,需要定时执行或周期性执行,为了实现这个需求,一般有以下几种方式选择:后台任务,即IHostedService开源库:Hangfire开源库:Quartz.net这里,说下Hangfire的使用。官网https://www.hangfire.io/Hangfire–Backgroundjobsandworkersfor.NET......
  • Netflix 网站架构学习
    Netflix网站架构学习Netflix架构的特点是他们没有自建数据中心,而是将服务直接架设在AWS的云服务上(EC2和S3),并通过自建CDNOpenConnect提供高质量的点播服务。Netflix采用微服务架构,将复杂业务流程拆解成独立的小型服务,服务间通过REST或RPC彼此调用。CDNCDN的主......
  • Qemu仿真----(7)运行Ubuntu Core
    平台:ubuntu-22.04-desktop-amd64.对象:ubuntucore、qemu、raspberrypi、genericx86pc.文件:ubuntu-core-22-amd64.img.xz、ubuntu-core-22-arm64+raspi.img.xz详细介绍通过Qemu运行ubuntucore,简单介绍x64电脑和树莓派上的使用方法。1.账号1.1注册ubuntu账号由于Ubuntu......
  • xxxxhttps://blog.csdn.net/holecloud/article/details/80139297
    #include"stdafx.h"#include<opencv2\imgproc\imgproc.hpp>#include<windows.h>#include<opencv2/opencv.hpp>#include<cmath>#include<iostream>//#include"DetectPackage.h"#include<cmath>usin......