前言

最近有朋友问我jwt的使用,有感而发写篇文章,由于一直使用框架开发,这些技术还真有些手生了,特此写篇文章做下笔记。

随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高,因此慢慢发展成为token的方式做登录身份校验,然后通过token去取redis中的缓存的用户信息,随着之后jwt的出现,校验方式更加简单便捷化,无需通过redis缓存,而是直接根据token取出保存的用户信息,以及对token可用性校验,单点登录更为简单。JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。适用于多客户端的前后端解决方案,JWT 是无状态化的,更适用于 RESTful 风格的接口验证。本文主要介绍使用JWT进行接口身份认证。

jwt介绍

JWT的结构体是什么样的?
JWT由三部分组成,分别是头信息、有效载荷、签名,中间以(.)分隔
(1)header(头信息) 描述 JWT 的元数据的JSON对象
由两部分组成,令牌类型(即:JWT)、散列算法(HMAC、RSASSA、RSASSA-PSS等)

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

(2)Payload(有效载荷)
JWT的第二部分是payload,其中包含claims。claims是关于实体(常用的是用户信息)和其他数据的声明,claims有三种类型: registered, public, and private claims。
一个用来存放实际需要传递的数据的JSON 对象。如:

"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin","exp": 1610877510,"iss": "cba","aud": "cba"
}

(3)Signature
要创建签名部分,必须采用编码的Header,编码的Payload,秘钥,Header中指定的算法,并对其进行签名。 对前两部分(Header、Payload)的签名,防止数据篡改。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

JWT示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJleHAiOjE2MTA4Nzc1MTAsImlzcyI6ImNiYSIsImF1ZCI6ImNiYSJ9.O9lbZwfqRuA6vKcRCfYieA1zLkTPppdSvTc8UzwCkNw

一.准备工作

Demo可以在我的资源中下载 Demo
https://download.csdn.net/download/qq_39569480/24392815
(1).添加NuGet程序包
Microsoft.AspNetCore.Authentication.JwtBearer

(2).appsettings.json

"JwtConfig": {"SecretKey": "123123123123", // 密钥   可以是guid 也可以是随便一个字符串"Issuer": "zhangsan", // 颁发者"Audience": "zhangsan", // 接收者"Expired": 30 // 过期时间(30min)},

二.创建JWT配置类

using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;/// <summary>/// jwt配置/// </summary>public class JwtConfig : IOptions<JwtConfig>{public JwtConfig Value => this;public string SecretKey { get; set; }public string Issuer { get; set; }public string Audience { get; set; }public int Expired { get; set; }public DateTime NotBefore => DateTime.UtcNow;public DateTime IssuedAt => DateTime.UtcNow;public DateTime Expiration => IssuedAt.AddMinutes(Expired);private SecurityKey SigningKey => new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey));public SigningCredentials SigningCredentials =>new SigningCredentials(SigningKey, SecurityAlgorithms.HmacSha256);}

三.创建JWT工具类

 public class GenerateJwt{private readonly JwtConfig _jwtConfig;public GenerateJwt(IOptions<JwtConfig> jwtConfig){_jwtConfig = jwtConfig.Value;}/// <summary>/// 生成token/// </summary>/// <param name="sub"></param>/// <param name="customClaims">携带的用户信息</param>/// <returns></returns>public JwtTokenResult GenerateEncodedTokenAsync(string sub, LoginUserModel customClaims){//创建用户身份标识,可按需要添加更多信息var claims = new List<Claim>{new Claim("userid", customClaims.userid),new Claim("username", customClaims.username),//new Claim("realname",customClaims.realname),//new Claim("roles", string.Join(";",customClaims.roles)),//new Claim("permissions", string.Join(";",customClaims.permissions)),//new Claim("normalPermissions", string.Join(";",customClaims.normalPermissions)),new Claim(JwtRegisteredClaimNames.Sub, sub),};//创建令牌var jwt = new JwtSecurityToken(issuer: _jwtConfig.Issuer,audience: _jwtConfig.Audience,claims: claims,notBefore: _jwtConfig.NotBefore,expires: _jwtConfig.Expiration,signingCredentials: _jwtConfig.SigningCredentials);string access_token = new JwtSecurityTokenHandler().WriteToken(jwt);return new JwtTokenResult(){access_token = access_token,expires_in = _jwtConfig.Expired * 60,token_type = JwtBearerDefaults.AuthenticationScheme,user = customClaims};}}

四.JwtTokenResult

登录成功生成jwt返回给前端的model,LoginUserModel是用户信息model,我这里携带是为了避免前端解析token。

/// <summary>/// 登录成功返回model/// </summary>public class JwtTokenResult{public string access_token { get; set; }public string refresh_token { get; set; }/// <summary>/// 过期时间(单位秒)/// </summary>public int expires_in { get; set; }public string token_type { get; set; }public LoginUserModel user { get; set; }}public class LoginUserModel{public string userid { get; set; }public string username { get; set; }public string realname { get; set; }public string roles { get; set; }public string permissions { get; set; }public string normalPermissions { get; set; }}

五.Startup配置

(1) .ConfigureServices注入jwt

             //注入jwtservices.AddScoped<GenerateJwt>();services.Configure<JwtConfig>(Configuration.GetSection("JwtConfig"));#region jwt验证var jwtConfig = new JwtConfig();Configuration.Bind("JwtConfig", jwtConfig);services.AddAuthentication(option =>{//认证middleware配置option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options =>{options.TokenValidationParameters = new TokenValidationParameters{//Token颁发机构ValidIssuer = jwtConfig.Issuer,//颁发给谁ValidAudience = jwtConfig.Audience,//这里的key要进行加密IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecretKey)),//是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比ValidateLifetime = true,};});#endregion

(2).Configure

 app.UseAuthentication();//要在授权之前认证

六.调用获取token

using JwtDemo.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;namespace JwtDemo.Controllers
{[Route("api/[controller]/[action]")][ApiController]public class TestController : Controller{private readonly GenerateJwt _generateJwt;public TestController(GenerateJwt generate) {this._generateJwt = generate;}[HttpGet]public ActionResult GetLogin(string name,string userid) {var claims = new LoginUserModel(){userid = userid,username = name,realname = name,//roles = string.Join(";", user.roles),//permissions = string.Join(";", user.permissions), };var refreshToken = Guid.NewGuid().ToString(); //当然  你要在生成token之前要验证一下账户是否在数据库存在  存在则生成/*数据库查询*/var jwtTokenResult = _generateJwt.GenerateEncodedTokenAsync(userid, claims);jwtTokenResult.refresh_token = refreshToken;return Json(jwtTokenResult);//这里可按需返回   如果不想返回用户信息  比如密码  可以在_generateJwt.GenerateEncodedTokenAsync去掉哦}}
}

swagger调试

postman请求

七.在后台中有时候我们需要获取当前用户的一些属性

JwtUser,用户解析jwt 获取当前用户信息

public static class JwtUser{/// <summary>/// 解析jwt 获取当前用户信息/// </summary>/// <param name="request"></param>/// <returns>用户信息</returns>public static LoginUserModel GetRequestUser(this HttpRequest request){var authorization = request.Headers["Authorization"].ToString();var auth = authorization.Split(" ")[1];var jwtArr = auth.Split('.');var dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(Base64UrlEncoder.Decode(jwtArr[1]));//解析Claimsvar reqUser = new LoginUserModel{userid = dic["userid"],username = dic["username"],realname = dic["realname"],roles = dic["roles"],permissions = dic["permissions"],normalPermissions = dic["normalPermissions"],};return reqUser;} }

控制器中这样获取

[HttpGet]public ActionResult GetUser() {var aa= JwtUser.GetRequestUser(this.Request);return Json(aa.userid+"===="+ aa.username); //获取到当前用户的姓名  角色等等就可以做一些业务处理}

八.使用

在接口上标记身份验证
[AllowAnonymous] 标记此标识的接口是不需要验证的
[Authorize] 标记此标识的接口需要验证

     [Authorize][HttpGet] public ActionResult GetDataList(string 参数){/*业务代码*/return Json("");}

也可以直接标记在控制器上
获取token的接口最好单独写在一个控制器

九.Swagger UI添加认证

在项目中通常都添加了Swagger UI来展示接口及基础测试,那么如果添加了认证后,如何在调用接口前添加认证信息呢?
  
   在Startup中:ConfigureServices中添加Swagger设置时,添加认证设置

#region 启用swagger验证功能//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称一致即可。c.AddSecurityRequirement(new OpenApiSecurityRequirement{{new OpenApiSecurityScheme{Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme,Id = "Bearer"}},new string[] { }}});c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme{Description = "JWT授权(数据将在请求头中进行传输) 在下方输入Bearer {token} 即可,注意两者之间有空格",Name = "Authorization",//jwt默认的参数名称In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)Type = SecuritySchemeType.ApiKey,BearerFormat = "JWT",Scheme = "Bearer",});#endregion

添加token即可
输入时 要输入Bearer +token 注意Bearer后有空格

ok感谢观看

.Net Core WebApi集成JWT实现身份认证相关推荐

  1. 如何简单的在 ASP.NET Core 中集成 JWT 认证?

    前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...

  2. Pulsar 中使用 JWT 进行身份认证

    Pulsar 中使用 JWT 进行身份认证 欢迎阅读 Pulsar 开源书籍<Pulsar入门与实践> 更好的阅读体验,请参考在线版本<使用 JWT 进行身份认证> Pulsa ...

  3. php 完全前后端分离使用jwt,前后端分离,在 angular 8 中利用 JWT 进行身份认证

    最近项目项目中用angular8进行前端开发,所以近期会收集整理angular相关的文章发出来,中间遇到的坑也会发出来.本文原文是angular6的,不过angular8同样适用. JWT 是什么,为 ...

  4. WebApi后端框架Token身份认证,Api接口Token验证

    令牌概述(Token) 在以用户账号体系作为安全认证的信息系统中,对用户身份的鉴定是非常重要的事情. 令牌机制是软件系统安全体系中非常重要的部分,在计算机身份认证中是令牌的意思,一般作为邀请.登录以及 ...

  5. .net core集成cas统一身份认证

    git源码地址:https://github.com/IUCrimson/AspNet.Security.CAS 安装 NuGet 包 PM> Install-Package AspNetCor ...

  6. asp net html.dropdownlist viewdata 指定选中项_ASP.NET Web API基础(05)--- 基于JWT的身份认证 - 高原秃鹫...

    5.1 Web API中的过滤器 WebApi下的过滤器和MVC下的过滤器有一些区别. (1)       所处命名空间不同. Web API 过滤器额命名空间是"",而MVC过滤 ...

  7. AntDesign Pro + .NET Core 实现基于JWT的登录认证

    很多同学说AgileConfig的UI实在是太丑了.我想想也是的,本来这个项目是我自己使用的,一开始甚至连UI都没有,全靠手动在数据库里修改数据.后来加上了UI也是使用了老掉牙的bootstrap3做 ...

  8. 基于JWT的身份认证学习笔记

    JSON Web Token(缩写JWT)是目前最流行的跨域认证解决方案. 一.跨域认证的问题 互联网服务离不开用户认证.一般流程是下面这样. 1.用户向服务器发送用户名和密码. 2.服务器验证通过后 ...

  9. .Net Core 2.1 JWT Bearer 的认证

    起因 最近想要学习一下 .net core 2.1 相关的知识,即是因为工作需要亦是在微服务和 docker 化的今天不得不去了解了解 .net core.API 第一步即是安全,即为认证(Authe ...

  10. Dynamics 365 CRM 接入统一身份认证平台(单点登录集成)

    打算将D365 CRM接入公司统一身份认证平台. 前提:D365 已IFD部署,因为要借助ADFS来完成单点登录. 登录ADFS服务器,打开ADFS,本次集成,统一身份认证为上游,ADFS是下游,因为 ...

最新文章

  1. HarmonyOS 点击事件的实现
  2. android 开启一个定时线程_Android异步、延迟和定时任务的简易用法
  3. Effect of Switchovers, Failovers, and Control File Creation on Backups
  4. 新建一个Windows Service的方法
  5. Python代码列主元消去法matlab编程_工业机器人用什么语言编程的?
  6. 字节跳动想取消大下周,遭到部分员工激烈反对
  7. 全球最畅销的10款手机:iPhone 11继续无敌,能对拼的只有它!
  8. 使用go制作微服务数据计算
  9. delphi与java_Delphi XE8中Delphi和JAVA数据类型对应关系!
  10. linux less 阻塞输出,linux – `less`命令显示输出所用的时间
  11. android imagebutton 点击效果缩小,imagebutton 设置点击和按压效果
  12. 【预测模型】人口结构可持续发展模型构建
  13. Learn Git Branching 答案汇总
  14. 58同城高性能移动Push推送平台架构演进之路
  15. python-字符串格式化(万古枯)
  16. java与模式(一)
  17. CSDN原力计划之技术影响力企业博客英雄榜 TOP 50 发布!
  18. inline-bock间隙问题
  19. mac 下备份同步qq聊天纪录
  20. postman 设置 中文版 9.2.0 汉化

热门文章

  1. python程序中name的作用_python编程中的if __name__ == '__main__': 的作用和原理
  2. 中国生态系统服务空间数据集/食物生产、土壤保持、水源涵养、防风固沙、生物多样性、碳固定
  3. 比较x^y和y^x的大小
  4. CNN LeNet-5 AlexNet VGG简介
  5. 求整数n次方以及矩阵n次方快速解法
  6. Hbase rowkey 设计原则
  7. linux存放日志的目录下,linux系统各种日志存储路径和详细介绍
  8. 红帽linux安装wordpress,linux Centos怎么安装wordpress
  9. 武大计算机专业学费多少,2017年武汉大学硕士研究生学费及奖助学金
  10. 图:乐清市首届民工艺术节闭幕式暨才艺表演决赛圆满结束_渤锐软件提供了【评委打分公开展示】技术支持