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

阅读本文你的收获

  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;//设置元数据地址或权限是否需要HTTPsoption.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.mzph.cn/news/600030.shtml

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

相关文章

网络故障问题一般性检查排查思路

一、基本连通性检查 在网络中ping是一个十分强大的TCP/IP工具。它可以用来检测网络的连通情况和分析网络速度、也可以ping网址根据域名得到服务器IP、同时我们根据ping返回的TTL值来判断对方所使用的操作系统及数据包经过路由器数量。 ping 网址&#xff0c;有几种输出情况&a…

Linkage Mapper 工具参数详解——Centrality Mapper

【小白一学就会无需其他教程】此文档用于解析使用Linkage Mapper 各输入输出参数详情以及可能的影响&#xff0c;并介绍了如何解释模型输出结果和输出参数&#xff0c;适合刚入手的人。篇幅很长很啰嗦&#xff0c;是因为每个参数都解释的万分细致。 从以下链接中获取内容&…

软件测试基础理论学习-常见软件开发模型

瀑布模型 背景 瀑布模型的概念最早在1970年由软件工程师Winston W. Royce在其论文《Managing the Development of Large Software Systems》中提出。Royce虽然没有明确提出“瀑布模型”这个术语&#xff0c;但他描述了一种线性的、阶段性的开发流程&#xff0c;各个阶段之间具…

Windows系统中Wireshark抓包工具的安装使用

在使用Windows服务器时&#xff0c;如果我们发现网络流量异常或存在异常的外发数据包行为&#xff0c;我们可以利用抓包工具来捕获网络流量包&#xff0c;并对这些流量包进行特征分析&#xff0c;以查看其来源和目的地。通过这些信息&#xff0c;我们可以进一步诊断问题。 以下…

Linux下NUMA 内存管理初步理解

LINUX 系统在多核下,以及NUMA架构技术下 如何管理物理内存? 经过初步了解 发现系统对内存有以下工作 1 映射 2 内存碎片 3 内存回收 4 内存池 5 冷热页 6 水位线和保留内存 7 支持内存条热插拔 8 大页管理 这些功能给人感觉,尤其是DBA感觉是重新实现了数据缓存池的功…

EG网关网口连接触控一体机操作说明V1.0 20210809

前言&#xff1a;工业现场中&#xff0c;很多情况下都会使用触摸屏连接PLC这一套设备&#xff0c;此一体机是将触摸屏和PLC两款设备集成到一起&#xff0c;可以简化现场设备结构&#xff0c;方便维护。同时&#xff0c;使用蓝蜂 EG系列网关&#xff0c;可以实现远程在线监控数据…

代码随想录算法训练营第十五天| 二叉树 513. 找树左下角的值 112. 路径总和 106.从中序与后序遍历序列构造二叉树

513. 找树左下角的值 层序遍历 本题用层序遍历可以直接秒了&#xff0c;直接提取每一层中最左边的元素&#xff08;i0&#xff09;&#xff0c;然后保存到最后一层即可。 class Solution { public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> que;int…

Java学习苦旅(十七)——栈和队列

本篇博客将详细讲解Java中的栈和队列。 文章目录 栈概念Java中Stack常用方法代码实现 队列概念队列常用方法对比QueueDeque 代码实现Queue 结尾 栈 概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一…

惊呆:RocketMQ顺序消息,是“4把锁”实现的(顺序消费)

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多关于RocketMQ 的、很重要的面试题&#xff1a; 如何保证RocketMQ消息有序&#xff1f; Ro…

应用层网络协议

tags: [“计算机网络”] descripution: “学习应用层的一些常用协议” 网络协议&#xff1a;约定的信息传输的格式&#xff0c;如几个字节是消息头、消息头记录什么信息之类的&#xff1b;c/s架构&#xff1a;不一定是两台计算机&#xff0c;而是两个应用、两个端口工具&#…

poium测试库之JavaScript API封装原理

为什么要封装JavaScript的API&#xff1f; 因为有些场景下Selenium提供的API并不能满足我们需求。比如&#xff0c;滑动浏览滚动条&#xff0c;控制元素的显示/隐藏&#xff0c;日历控件的操作等&#xff0c;都可以通过JavaScrip实现&#xff0c;而且Selenium为我们提供了 exe…

教你直接在 Midjourney 网站上创建图像

经过一年多的工作和使用 Midjourney 的乐趣&#xff0c;我们终于能够直接在网站上生成图像。许多以前没有使用过 Discord 的人对于只能在 Discord 上创建图像并不满意。现在&#xff0c;几乎所有人的等待终于结束了。 直接在 Midjourney 网站上生成图像 David Holz 在 Discor…

SSM电影售票管理系统----计算机毕业设计

项目介绍 管理员角色包含以下功能&#xff1a; 管理员登陆,管理员用户管理,新闻公告增删改查,电影类型增删改查,影院信息增删改查,电影信息增删改查,订单查询,电影评价管理等功能。 用户角色包含以下功能&#xff1a; 用户首页,用户登录,查看电影详情,加入购物车,下单电影票,…

数据结构:图详解

图的存储方式 邻接矩阵 首先先创建图&#xff0c;这一个我们可以使用邻接矩阵或者邻接链 表来进行存储&#xff0c;我们要实现的无向图的创建&#xff0c;我们先创建 一个矩阵尺寸为n*n&#xff0c;n为图中的节点个数如图所示 可以看出图中有5个结点&#xff0c;那我们创建…

基于web3.js和ganache实现智能合约调用

目的&#xff1a;智能合约发布到本地以太坊模拟软件ganache并完成交互 准备工作&#xff1a; web3.jsganache模拟软件 ganache参数配置 从ganache获取一个url&#xff0c;和一个账号的地址&#xff0c; url直接使用图中的rpc server位置的数据即可 账号address从下列0x开头…

SpringBoot中动态注册接口

1. 说明 接口注册&#xff0c;使用RequestMappingHandlerMapping来实现mybatis中动态执行sql使用github上的SqlMapper工具类实现 2. 核心代码片段 以下代码为spring动态注册接口代码示例 Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping;publ…

进程控制-操作系统

1. 进程概述 进程和程序的区别:程序和进程是两个不同的概念&#xff0c;他们的状态&#xff0c;占用的系统资源都是不同的。 程序&#xff1a;就是磁盘上的可执行文件文件, 并且只占用磁盘上的空间&#xff0c;是一个静态的概念。进程&#xff1a;被执行之后的程序叫做进程&a…

Maven之依赖的传递

问题导入 1. 依赖传递 A依赖B&#xff0c;B依赖C&#xff0c;A是否依赖于C呢&#xff1f;–A依赖于C 依赖具有传递性 路径优先&#xff1a;当依赖中出现相同的的资源时&#xff0c;层级越深&#xff0c;优先级越低&#xff0c;层级越浅&#xff0c;优先级越高 声明优先&…

nacos 2.* 部署在linux服务器无法注册问题

通过sdk注册代码 报错 Exception in thread "main" ErrCode:-401, ErrMsg:Client not connected, current status:STARTING at com.alibaba.nacos.common.remote.client.RpcClient.request(RpcClient.java:639) at com.alibaba.nacos.common.remote.client…

【网络编程】——基于TCP协议实现回显服务器及客户端

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、TCP实…