ASP.NET Core高级之认证与授权(一)--JWT入门-颁发、验证令牌

news2025/7/15 11:58:13

阅读本文你的收获

  1. 了解认证和授权的作用
  2. 了解在ASP.NET Core中实现身份认证的技术都有哪些
  3. 学习基于JWT认证并学会颁发和验证JWT令牌

一、重要的前置概念

在一个系统中,不是所有的功能和资源都能够被自由地访问,比如你存在银行系统里面的资金,不可能给我去提取,对吧。这就需要系统对用户进行一些访问的控制,从而使系统更加地安全。
Authentication(认证)和Authorization(授权)都是用于访问控制的概念,目的是确保只有合法用户可以访问系统资源。

  • Authentication(认证)是指验证用户身份的过程。通过认证,系统能够确认用户是真实的,准确地知道用户是谁。常见的认证方式包括用户名和密码、指纹识别、身份证验证等。认证成功后,用户才能被认为是合法用户,可以继续访问系统资源。

  • Authorization(授权)是指确定用户是否有权限访问特定资源的过程。认证成功后,系统需要根据用户的角色、权限等信息来判断用户是否有权访问某个资源。授权机制可以基于用户角色或权限级别进行,例如管理员拥有更高的权限,能够访问更多的资源,而普通用户只能访问受限资源。授权也可以是细粒度的,例如给用户赋予特定的操作权限,如读取、写入、删除等。

在ASP.NET Core中,可以使用以下技术实现身份认证(包括但不限于):

  1. Cookie身份认证:使用ASP.NET Core的认证中间件,将用户的认证信息存储在cookie中。可以使用AddAuthenticationAddCookie方法配置Cookie身份认证。

  2. JWT(JSON Web Token)身份认证:使用JWT作为认证令牌,将用户的认证信息加密并传输给客户端。可以使用AddJwtBearer方法配置JWT身份认证。

  3. OAuth身份认证:使用OAuth协议进行身份认证,允许用户使用第三方身份提供者进行登录。可以使用AddAuthenticationAddOAuth方法配置OAuth身份认证。

  4. OpenID Connect身份认证:基于OAuth协议的扩展,提供了更加丰富的身份认证功能。可以使用AddAuthenticationAddOpenIdConnect方法配置OpenID Connect身份认证。

  5. Session认证:ASP.NET Core中可以使用AddSession方法来配置会话认证。在使用会话认证时,服务器会为每个用户创建一个会话对象,并分配一个唯一的会话ID。服务器会将该会话ID存储在用户的浏览器cookie中,并在后续的请求中使用该会话ID来验证用户的身份。

以上技术可以根据具体的需求和场景进行选择和配置,也可以组合使用来实现更加复杂的身份认证方案。

二、JWT是什么?

JWT:JSON Web Token (JSON网络令牌)里面存的是JSON格式的数据,有三部分组成,以.号做分割, 头部.荷载.防伪签名, 经过一定的加密算法来生成。

作用:颁发给登录的用户,用户拿着这个令牌作为身份的凭证,来访问后续的授权资源。

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

2.1 JWT的组成结构

JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:

  • Header – 头部
  • Payload -荷载
  • Signature -签名

例子:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJMb2dpbk5hbWUiOiJhZG1pbiIsIlN1cGVyQWRtaW4iOiJ0cnVlIiwibmJmIjoxNjM5NTQ4MDYyLCJleHAiOjE2Mzk1NDgyNDIsImlzcyI6IldYRiIsImF1ZCI6IkV2ZXJ5VGVzdE9uZSJ9.rfMYR5h26sv3j-WrjVgqB0K05fr9M4wFgCx4leZnqg8

可以到jwt.io官网上将以上JWT字符串进行调试,解析出原始的JSON数据。
在这里插入图片描述

2.2 JWT加密组装的过程

JWT令牌=Base64编码的header.Base64编码的payload.Base64编码的signature;
而signature又是通过HS256这种算法将Base64编码的header.Base64编码的payload的字符串进行加密所得。请看下面的演示代码:

//头部
header = {"alg": "HS256", "typ": "JWT"}
//荷载
payload = {"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
//生成签名
key = "secretkey123qwe!@#" //密钥可以自己设置
unsignedToken = encodeBase64(header) + '.' + encodeBase64(payload)  
signature = HMAC-SHA256(key, unsignedToken) 

//最后的JWT Token如下:
token = encodeBase64(header) + '.' + encodeBase64(payload) + '.' + encodeBase64(signature) 

二、JWT的使用场景

(1)Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。

(2)Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。

三、 JWT认证入门案例

开发环境:

操作系统: Windows 10 专业版
平台版本是:.NET 6
开发框架:ASP.NET Core WebApi
开发工具:Visual Studio 2022

3.1、颁发令牌

  1. 登录成功后,给用户颁发一个JWT的令牌
//引用命名空间
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;

namespace XfTech.Demo.WebApi.Controllers;

[Route("api/[controller]/[action]")]
[ApiController]
[Authorize]
public class AccountController : ControllerBase
{    
	/// <summary>
	/// 登录功能
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost]
	[Route("Login")]
	[AllowAnonymous] //此方法允许匿名访问
	public IActionResult Login(LoginDto input)
	{
		//第一步做模型验证
		if(!ModelState.IsValid) {
			//如果输入的参数无效,则直接返回
			return BadRequest();  //返回一个400状态码
		}
		//获取用户(根据输入的用户名和密码做查询,如果用户不为null则登录信息有效,具体请自行实现)
		var user = _userService.GetUser(input);
		if(user == null)
		{
			return Ok(new { Code=-1, Msg="用户登录不成功"});
		}
	
		//荷载信息
		List<Claim> claims = new List<Claim>()
		{
			new Claim(ClaimTypes.Name, user.UserName),
			new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
	        //new Claim("role","guest"),
	        //new Claim("sex","男")
		};
	
		//签名密钥
		var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("qwerty123456sdgdgsdgfsdgfsfdg"));
		//对秘钥加密
		var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
	
		//过期时间
		DateTime expires = DateTime.Now.AddSeconds(2*3600); //设置了2小时
	
		//实例化JWT安全令牌对象
		var jwtToken = new JwtSecurityToken(
			issuer:   "XF",            //发布者
			audience: "everyone",      //受众(发布给谁用)
			claims:   claims,          //发起人 订阅者
			expires:  expires,//过期时间
			signingCredentials: credentials);   //秘钥
	
		//序列化jwt令牌 从而得到一个字符串
		string strToken = new JwtSecurityTokenHandler().WriteToken(jwtToken);
	
		return Ok(new  { 
			AccessToken = strToken,
			Code = 0, 
			Msg = "用户登成功", 
			Data = user });
	}    
}

3.2、验证用户登录(验证JWT令牌)

要想使用JWT进行用户身份验证,必须使用UseAuthentication中间件; 在Program
.cs注册Authentication服务。AddAuthenticationAddJwtBearer方法。

//下载NuGet包
Microsoft.AspNetCore.Authentication.JwtBearer
    
//配置服务
builder.Services.AddAuthentication(option =>
{
	//认证模式
	option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
	//质询模式
	option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
	option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(option =>
{
	option.RequireHttpsMetadata = false;//设置元数据地址或权限是否需要HTTPs
	option.SaveToken = true;
	//Token验证参数
	option.TokenValidationParameters = new TokenValidationParameters
	{
		ValidateIssuerSigningKey = true, //是否验证签名
		IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("qwerty123456sdgdgsdgfsdgfsfdg")),
		ValidIssuer = "XF",         //有效的发行人
		ValidAudience = "everyone", //有效的受众
		ValidateIssuer = true,      //是否验证发行人
		ValidateAudience = true,    //是否验证受众
		ClockSkew = TimeSpan.Zero,
		ValidateLifetime = true     //是否验证过期时间
	};
});    

//.....

  //启用身份验证中间件(不要遗漏哦)
  app.UseAuthentication(); 
  app.UseAuthorization();

3.3 、接口测试-检查JWT验证是否有效

  1. 用[Authorize]特性保护Api
    在Api控制器或者方法上,加[Authorize]特性,需要引用命名空间:

using Microsoft.AspNetCore.Authorization;

  • [Authorize]加在控制器上,则该控制器下所有API方法需要身份授权后才能访问;
  • [Authorize]加在方法上,则仅该方法需要身份授权后才能访问。

另外,有一个[AllowAnonymous]特性,加在Api控制器或者方法上,允许匿名访问该Api或者控制器下所有Api方法。
在这里插入图片描述
Api资源被锁保护起来之后,如果没有登录直接访问,则会报401的错误。在Swagger中测试截图如下:
在这里插入图片描述

  1. ApiPost接口测试工具来测试

测试JWT
登录之后拿到了Token令牌,再测试创建用户接口,就能正常返回数据了。

加上头部信息再测试


本次是JWT的简单入门,下次我们会对这个JWT进行封装。
如果本文对你有帮助的话,请点赞+评论+关注,或者转发给需要的朋友。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1356058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Rust 圣经 阅读 字符、布尔、单元类型

字符类型&#xff08;char&#xff09; Rust 的字符不仅仅是 ASCII &#xff0c;还包含所有的 Unicode 值&#xff0c;包括单个的中文、日文、表情符号等等。 Unicode 值的范围从 U0000 ~ UD7FF 和 UE000 ~ U10FFFF。 因为每个 Unicode 都是 4 个字节编码&#xff0c;所以字符…

Mybatis之多表查询

目录 一、简介 1、使用嵌套查询: 2、使用多个 SQL 语句&#xff1a; 3、使用关联查询&#xff1a; 4、使用自定义映射查询&#xff1a; 二、业务场景 三、示例 1、一对一查询 2、一对多查询 一、简介 MyBatis 是一个优秀的持久层框架&#xff0c;它提供了强大的支持来执…

向日葵远程工具的使用Mysql5.7的安装与配置

目录 一、向日葵远程安装与使用 二、Mysql 5.7 安装与配置 2.1 安装 2.2 Navicat Premium 12 测试连接 本机测试连接 外部访问MySQL测试连接 三、思维导图 一、向日葵远程安装与使用 简介&#xff1a; 向日葵远程控制是一款用于对远程PC进行管理和服务的软件,拥有5秒快速…

二阶偏导数(隐函数)

定义&#xff0c;方法 一般型 复杂型

如何修复 SQL Server 数据库中的恢复挂起状态?

当我们想与关系数据库交互时&#xff0c;SQL 就会出现并帮助用户与数据库进行交互。SQL 从高级语言中获取用户的输入&#xff0c;然后访问将代码转换为机器可理解的形式。SQL 确实会恢复数据库文件&#xff0c;但有时 SQL 服务器恢复暂挂阶段会进入帐户&#xff0c;这会停止恢复…

海外数据中心代理与住宅代理:优缺点全面对比

数据中心代理和住宅代理是为了匿名而开发的&#xff0c;通过替换网站眼中您自己的 IP 地址。然而&#xff0c;它们在价格、功能、性能或最佳用例方面存在一些差异。那么&#xff0c;这些代理类型到底有什么相似点和不同点呢&#xff1f; 一、什么是数据中心代理&#xff1f; 1…

Hive用户自定义函数之UDF开发

在进行大数据分析或者开发的时候&#xff0c;难免用到Hive进行数据查询分析&#xff0c;Hive内置很多函数&#xff0c;但是会有一部分需求需要自己开发&#xff0c;这个时候就需要自定义函数了&#xff0c;Hive的自定义函数开发非常方便&#xff0c;今天首先讲一下UDF的入门开发…

人工智能大模型:定义、发展和应用

⭐简单说两句⭐ ✨ 正在努力的小新~ &#x1f496; 超级爱分享&#xff0c;分享各种有趣干货&#xff01; &#x1f469;‍&#x1f4bb; 提供&#xff1a;模拟面试 | 简历诊断 | 独家简历模板 &#x1f308; 感谢关注&#xff0c;关注了你就是我的超级粉丝啦&#xff01; &…

【基础python】条件语句 | 循环

条件语句 if elif else python中和绝大数语言类似&#xff0c;具有能够判断语句顺序的语法 if elif else 分别对应C的 if else if else if 条件为真进入语句 &#xff0c;反之则不进入 如果if 为假&#xff0c;存在else 则会进入else 如果if 为假 &#xff0c;存在…

数据库分区分表

分区分表 为什么要分库分表 软件时代&#xff0c;传统应用都有这样一个特点&#xff1a;访问量、数据量都比较小&#xff0c;单库单表都完全可以支撑整个业务。随着互联网的发展和用户规模的迅速扩大&#xff0c;对系统的要求也越来越高。因此传统的MySQL单库单表架构的性能问…

探索 Vue 实例方法的魅力:提升 Vue 开发技能(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Spring的bean的生命周期!!!

一.单例模式 单例&#xff1a;[启动容器]--->通过构造方法&#xff08;创建对象&#xff09;---->调用set方法&#xff08;注入&#xff09;--->调用init方法&#xff08;初始化&#xff09;----[容器关闭]----->调用destroy方法&#xff08;销毁&#xff09; app…

教你用python画图—Turtle详细教程

Turtle模块绝对是吸引非专业代码开发者人员学习python入门的好工具 通过turtle几行代码的执行软件就会画出漂亮的图形&#xff0c;美观而且有成就感&#xff0c;这样一下子对python编程就产生了兴趣。 这些漂亮的图形如三角形、五角星、机器猫等。在写代码的时候改变几个参数…

反距离加权水平内插,附matlab代码(ERA5和GNSS站点不并址的处理方法之水平补偿)

1.内插方法 我在学习过程&#xff0c;内插方法为反距离加权水平内插&#xff0c;分享我的方法和公式&#xff0c;以及matlab代码。 2.使用该内插法的原因 GNSS与ERA5格网位置不并址&#xff0c;需要进行水平方向和垂直方向的补偿的补偿获得。水平方向不并址如第3节图所示&am…

数字人私人定制

数字人是什么&#xff1f; 在回答这个问题之前&#xff0c;我们先回答另一个问题&#xff0c;人如何与人工智能交流&#xff1f;目前可以通过文字、语音、电脑屏幕、手机屏幕、平板、虚拟现实设备等和人工智能交流&#xff0c;为了得到更好的交流体验&#xff0c;人工智能必然…

css sourcemap 源代码映射

vue.config.js css: {// Enable CSS source maps.sourceMap: process.env.NODE_ENV ! production, }重新运行&#xff1a;yarn serve 效果&#xff1a;

three.js Raycaster(鼠标点击选中模型)

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div class"box-right"…

LiveGBS流媒体平台GB/T28181功能-国标级联对接海康大华宇视华为等上级平台选择通道支持只看已选只看未选

LiveGBS功能国标级联对接海康大华宇视华为等上级平台选择通道支持只看已选只看未选 1、国标级联2、只看已选3、只看未选4、搭建GB28181视频直播平台 1、国标级联 LiveGBS可以作为下级平台&#xff0c;级联到第三方国标平台&#xff0c;详见&#xff1a; LiveGBS国标GB/T28181流…

dctcp 可扩展、低时延图解

理想 reno 和理想 dctcp 的单流 cwnd-time 演化图如下&#xff1a; 很直观地展现出 dctcp 锯齿小很多&#xff0c;锯齿小意味着高效。 dctcp 利用交换机反馈而来的 ecn 可精确计算导致排队超过 k 的报文比例&#xff0c;减去这一比例的 inflight 就是合适的。但 dctcp 在 re…