ASP.NET Core Web API用户身份验证
一、JWT介绍
ASP.NET Core Web API用户身份验证的方法有很多,本文只介绍JWT方法。JWT实现了服务端无状态,在分布式服务、会话一致性、单点登录等方面凸显优势,不占用服务端资源。简单来说,JWT的验证过程如下所示:
(1)通过用户名和密码获取一个Token。
(2)访问API时,加上这个Token。
Token包含过期时间、用户角色等信息,可以在多种场合灵活使用。
二、基本认证
2.1 场景描述
在基本认证的场景中,我们假设有一个Controller,代码如下所示:
[ApiController]
[Route("test")]
public class TestController : ControllerBase
{[HttpGet]public string Get(){return "success";}
}
这个Controller非常简单,就是访问之后返回"success"这个字符串。
现在,我们希望用户登录之后(提供用户名和密码)才能使用此API。
2.2 开发步骤
1、在NuGet中添加Microsoft.AspNetCore.Authentication.JwtBearer。
2、在Program.cs中,对builder.Services添加认证服务:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>{opt.TokenValidationParameters = new TokenValidationParameters(){ValidateIssuer = false,ValidateAudience = false,ValidateLifetime = false,ValidateIssuerSigningKey = false};});
在上面的参数中,可以根据使用场景进行灵活配置,这个后面会介绍。在此,使用最简单的配置。
3、同样在Program.cs中,添加以下语句:
app.UseAuthentication();
需要注意的是,此句需要在页面路由之前,例如是app.UseHttpsRedirection();之前,如下所示:
app.UseAuthentication();app.UseHttpsRedirection();app.UseAuthorization();app.MapControllers();app.Run();
4、在需要认证的Controller或某个具体方法上加上[Authorize]标记。例如我们在一开始介绍的API上加上标记:
[Authorize]
[HttpGet]
public string Get()
{return "success";
}
此时,如果再去访问此API,就会返回401没有权限的错误。
5、创建登录的Controller,也就是通过用户名和密码获取Token。
[Route("api/auth")]
[ApiController]
public class AuthController : ControllerBase
{[HttpPost]public string Gettoken(string username, string password){if (username == "admin" && password == "123456"){var claims = new[]{new Claim(ClaimTypes.Name, username)};var jwttoken = new JwtSecurityToken(claims: claims);var token = new JwtSecurityTokenHandler().WriteToken(jwttoken);return token;}return "用户不存在或密码错误";}
}
上面的用户认证简单的做了字符串比对,实际上可以通过查数据库的方法验证用户是否合法。
至此,用户验证的后端就开发完成了。
三、前端访问API
3.1 通过Swagger测试
很多时候,我们使用Swagger来测试API,但默认的Swagger配置没有用户验证,需要进行添加。
打开Program.cs,把builder.Services.AddSwaggerGen();这一句修改为:
builder.Services.AddSwaggerGen(c =>
{c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme(){In = ParameterLocation.Header,Type = SecuritySchemeType.ApiKey,Description = "Bearer Token",Name = "Authorization",BearerFormat = "JWT",Scheme = "Bearer"});c.AddSecurityRequirement(new OpenApiSecurityRequirement() {{new OpenApiSecurityScheme(){Reference=new OpenApiReference(){Type=ReferenceType.SecurityScheme,Id="Bearer"}},new string[]{ }}});
});
此时,打开Swagger,就会看到右上角有一个Authorize的按钮,如下图所示:

点击按钮,会要求输入一个Token。我们从上面写的登录Controller(AuthController)获取。如下图所示:

最下面的响应字符串就是我们要的Token。把这个Token填入到上面弹出的对话框中,注意需要在字符串前加上“Bearer ”。如下图所示:

此时,再去访问TestController,就会返回成功结果。
3.2 前端访问方法
在无用户验证要求的时候,前端访问TestController的代码如下所示:
fetch("https://localhost:28911/test", {method: "GET"
}).then(resp => {return resp.text();
}).then(data => {console.log(data);
}).catch(err => {console.log(err)
});
API前加上[Authorize]之后,上述调用也会返回401错误。上述调用需要把Token加入到Header中。
fetch("https://localhost:28911/test", {method: "GET",headers: {"Authorization": "Bearer eyJhbGciOiJ...太长,Token后面省略"}
}).then(resp => {return resp.text();
}).then(data => {console.log(data);
}).catch(err => {console.log(err)
});
此时,即可再次成功获取结果。
四、常见用户身份验证场景
4.1 Token有效期
一般情况下,通过用户名和密码得到了Token之后,我们不希望这个Token是永久有效的。也就是说,过了一段时间之后,Token失效,用户需要重新登录。
需要增加有效期,有几处地方需要修改。
首先是Program.cs中,原来的配置如下所示:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>{opt.TokenValidationParameters = new TokenValidationParameters(){ValidateIssuer = false,ValidateAudience = false,ValidateLifetime = false,ValidateIssuerSigningKey = false};});
需要把ValidateLifetime改为true:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>{opt.TokenValidationParameters = new TokenValidationParameters(){ValidateIssuer = false,ValidateAudience = false,ValidateLifetime = true,ClockSkew = TimeSpan.FromSeconds(30),};});
然后在AuthController的Gettoken方法里,加上有效期:
var claims = new[]{new Claim(JwtRegisteredClaimNames.Nbf,new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()) ,new Claim(JwtRegisteredClaimNames.Exp,new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds().ToString()),new Claim(ClaimTypes.Name, username)
};
上面配置的有效期是30分钟。
至此,当获得一个新的Token之后,经过30分钟,这个Token就无法使用了。
4.2 第三方验证
很多网站上提供QQ登录、微信登录、微博登录等功能,我们以微信登录进行说明。如果我们需要使用微信登录,需要到微信开发者平台注册,拿到一个叫AppKey的东西。这个AppKey相当于一个私钥,是不能让别人看到的。因为我们要使用微信的登录验证服务,这个服务不能向任何人提供,而且需要区分是哪个第三方在使用服务。
为了实现上述功能,认证时加入了一个IssUser的概念,也就是哪些APP可以调用服务。
在Program.cs中,修改配置:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>{opt.TokenValidationParameters = new TokenValidationParameters(){ValidateIssuer = true,ValidateAudience = false,ValidateLifetime = false,ValidateIssuerSigningKey = true,ValidIssuer = "App名称",IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("App私钥"))};});
然后,在Gettoken时,进行修改:
var claims = new[]{new Claim(ClaimTypes.Name, username)
};
var m5dkey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("App私钥"));
var creds = new SigningCredentials(m5dkey, SecurityAlgorithms.HmacSha256);
var jwttoken = new JwtSecurityToken(issuer: "App名称",claims: claims,expires: DateTime.Now.AddMinutes(30),signingCredentials: creds
);
var token = new JwtSecurityTokenHandler().WriteToken(jwttoken);
return token;
4.3 角色或权限
很多时候,用户登录之后,并不是可以访问所有的API。用户可以分出不同的角色,不同的角色可以访问不同的资源。
要做到这一点,首先在Gettoken时,把用户的角色加入到Token中。
var claims = new[]{new Claim(ClaimTypes.Name, username),new Claim("Role", "admin")
};
然后,在API前,指明此资源需要什么角色。
[Authorize(Roles = "admin")]
[HttpGet]
public string Get()
{return "success";
}
这样,按角色分配资源的功能就完成了。
相关文章:
ASP.NET Core Web API用户身份验证
一、JWT介绍 ASP.NET Core Web API用户身份验证的方法有很多,本文只介绍JWT方法。JWT实现了服务端无状态,在分布式服务、会话一致性、单点登录等方面凸显优势,不占用服务端资源。简单来说,JWT的验证过程如下所示: &a…...
785. 快速排序
785. 快速排序 给定你一个长度为 n n n 的整数数列。 请你使用快速排序对这个数列按照从小到大进行排序。 并将排好序的数列按顺序输出。 输入格式 输入共两行,第一行包含整数 n n n。 第二行包含 n n n 个整数(所有整数均在 1 ∼ 1 0 9 1 \th…...
C6678学习-IPC
文章目录 1、简介2、模块MultiProc静态设置(cfg设置)动态设置 IPCNotifyMessageQShareRegion 1、简介 IPC: Inter-Processor Communication 处理器间通信,指提供多处理器环境中的处理器之间的通信、相同处理器不同线程间的通信。包括数据传递…...
利用 Delte-Sigma ADC简化电路设计
很多时候在电路中选择合适的 ADC可以很大程度上简化前端的电路。这里我们一起来看一个电阻电桥的例子: 这里用到了一只仪表放大器和一只运算放大器,他们实际上主要完成了三个功能: 1. 抑制了 2.5V的共模信号; 2. 将-1…...
如何在 Windows 11 启用 Hyper-V
准备在本机玩一下k8s,需要先启用 Hyper-V,谁知道这一打开,没有 Hyper-V选项: 1、查看功能截图: 2、以下文件保存记事本,然后重命名为*.bat pushd "%~dp0" dir /b %SystemRoot%\servicing\Packa…...
哈希表企业应用-DNA的字符串检测
DNA的字符串检测-引言 若干年后, ikun DNA 检测部成立,专门对 这些ikun的解析检测 突然发现已经完全控制不了 因为学生已经会了 而且是太会了 所以DNA采用 以下视频测试: ikun必进曲 ikun必经曲 ikun必阶曲 如何感受到了吧!,如果你现在唱跳并且还Rap 还有打篮球 还有铁山靠 那…...
Kafka运维与监控
Kafka运维与监控 Kafka运维与监控一、简介二、运维1.安装和部署安装部署 2.优化参数配置配置文件高级配置分区和副本设置分区数量设置副本数量设置 网络参数调优传输机制设置连接数和缓冲区大小设置 消息压缩和传输设置消息压缩设置消息传输设置 磁盘设置和文件系统分区磁盘容量…...
【Redis—哨兵机制】
文章目录 概念哨兵机制如何工作的监控(如何判断主节点真的故障了)哪个哨兵进行主从故障转移?故障转移流程哨兵集群 概念 当进行主从复制时,如果主节点挂掉了,那么没有主节点来服务客户端的写操作请求了,也…...
MySQL学习笔记第七天
第07章单行函数 2. 数值函数 2.4 指数函数、对数函数 函数用法POW(x,y),POWER(X,Y)返回x的y次方EXP(X)返回e的x次方,其中e是一个常数,2.718281828459045LN(X),LOG(X)返回以e为底的X的对数,当x<0时,返…...
中级软件设计师备考---程序设计语言和法律法规知识
目录 需要掌握的程序语言特点法律法规知识---保护期限法律法规知识---知识产权人确定法律法规知识---侵权判定标准化基础知识 需要掌握的程序语言特点 Fortran语言:科学计算、执行效率高Pascal语言:为教学而开发的、表达能力强,演化出了Delp…...
Leetcode434. 字符串中的单词数
Every day a leetcode 题目来源:434. 字符串中的单词数 解法1:istringstream 我们知道,C默认通过空格(或回车)来分割字符串输入,即区分不同的字符串输入。 istringstream类用于执行C风格的串流的输入操…...
C++ cmake工程引入qt6和Quick 教程
目录标题 前言QML简介锻炼C水平 cmake修改方法方式一(qt6_add_resources)方式二 (qt_add_qml_module ) 其他相关知识为什么会有_other_files?qt_standard_project_setup() 函数qt_add_qml_module() 和 qt6_add_resources()的方式差异const QU…...
JavaEE - 网络编程
一、网络编程基础 为什么需要网络编程? 用户在浏览器中,打开在线视频网站,如优酷看视频,实质是通过网络,获取到网络上的一个视频资源。 与本地打开视频文件类似,只是视频文件这个资源的来源是网络。 相比本…...
【Android车载系列】第11章 系统服务-SystemServer自定义服务
1 编写自定义系统服务 1.1 AIDL接口定义 系统源码目录/frameworks/base/core/java/android/app/下新建AIDL接口IYvanManager.aidl package android.app;/** * 目录:/frameworks/base/core/java/android/app/IYvanManager.aidl */ interface IYvanManager{String …...
Lerna
Lerna Lerna是一个优化基于gitnpm的多pagkage项目的管理工具 解决的痛点 痛点一:重复操作 多Package本地link多Package依赖安装多Package单元测试多Package代码提交多Package代码发布 痛点二:版本一致性 发布时版本一 致性发布后相互依赖版本升级 package越多,管…...
迁移学习 pytorch
迁移学习(Transfer Learning)是通过使用一个预训练模型来快速训练一个新的网络模型,通常应用于数据集较小或计算资源较少的情况下。在 PyTorch 中,由于 torchvision 库中已经内置了一些经典的预训练模型,因此我们可以通过简单的调用函数来实现迁移学习。 下面是一个基于 …...
【python】keras包:深度学习( RNN循环神经网络 Recurrent Neural Networks)
RNN循环神经网络 应用: 物体移动位置预测、股价预测、序列文本生成、语言翻译、从语句中自动识别人名、 问题总结 这类问题,都需要通过历史数据,对未来数据进行预判 序列模型 两大特点 输入(输出)元素具有顺序关系…...
vue框架快速入门
vue 1、第一个Vue程序1.1、什么是Vue程序1.2、为什么要使用MVVM1.3、Vue1.4、第一个vue程序 2、基础语法2.1、v-bind2.2、v-if, v-else2.3、v-for2.4、v-on 3、Vue表单双绑、组件3.1、什么是双向数据绑定3.2、在表单中使用双向数据绑定3.3、什么是组件 4、Axios异步…...
Java连接顺丰开放平台
今天使用Java去访问顺丰的开放平台时,JSON转换一直不成功,最终发现是 可以看到这里是 "apiResultData": "{\"success\": .........它是以 " 开头的!!!如果是对象的话,那么…...
前端三剑客 - HTML
前言 前面都是一些基础的铺垫,现在就正式进入到web开发环节了。 我们的目标就是通过学习 JavaEE初阶,搭建出一个网站出来。 一个网站分成两个部分: 前端(客户端) 后端(服务器) 通常这里的客户端…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...
