asp.net core使用identity+jwt保护你的webapi(二)——获取jwt token
前言
上一篇已经介绍了identity在web api中的基本配置,本篇来完成用户的注册,登录,获取jwt token。
开始
开始之前先配置一下jwt相关服务。
配置JWT
首先NuGet安装包:
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.10" />
appsettings.json中添加jwt配置:
"JwtSettings": {
"SecurityKey": "qP1yR9qH2xS0vW2lA3gI4nF0zA7fA3hB",
"ExpiresIn": "00:10:00"
}
为了方便,新建一个配置类JwtSettings:
public class JwtSettings
{
public string SecurityKey { get; set; }
public TimeSpan ExpiresIn { get; set; }
}
在Startup中配置jwt:
public void ConfigureServices(IServiceCollection services)
{
//省略......
var jwtSettings = Configuration.GetSection(nameof(JwtSettings)).Get<JwtSettings>();
services.AddSingleton(jwtSettings);
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.SecurityKey)),
ClockSkew = TimeSpan.Zero,
};
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => { options.TokenValidationParameters = tokenValidationParameters; });
}
最后别忘了UseAuthentication:
app.UseAuthentication(); // add
app.UseAuthorization();
结构搭建
下面把项目基本结构搭建好,做好接口,后面实现:

以下是各个类的定义:
// 用户注册请求参数
public class RegisterRequest
{
public string UserName { get; set; }
public string Password { get; set; }
public string Address { get; set; }
}
// 用户登录请求参数
public class LoginRequest
{
public string UserName { get; set; }
public string Password { get; set; }
}
// 注册 登录 成功后返回 token
public class TokenResponse
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }
[JsonPropertyName("token_type")]
public string TokenType { get; set; }
}
// 登录 注册 失败时返回错误信息public class FailedResponse{ public IEnumerable<string> Errors { get; set; }}
// IUserService 接口public interface IUserService{ Task<TokenResult> RegisterAsync(string username, string password, string address); Task<TokenResult> LoginAsync(string username, string password);}
// UserService 实现public class UserService : IUserService{ public Task<TokenResult> RegisterAsync(string username, string password, string address) { throw new System.NotImplementedException(); } public Task<TokenResult> LoginAsync(string username, string password) { throw new System.NotImplementedException(); }}
// TokenResult 定义public class TokenResult{ public bool Success => Errors == null || !Errors.Any(); public IEnumerable<string> Errors { get; set; } public string AccessToken { get; set; } public string TokenType { get; set; }}
最后是UserController:
[Route("api/[controller]")][ApiController]public class UserController : ControllerBase{ private readonly IUserService _userService; public UserController(IUserService userService) { _userService = userService; } [HttpPost("Register")] public async Task<IActionResult> Register(RegisterRequest request) { var result = await _userService.RegisterAsync(request.UserName, request.Password, request.Address); if (!result.Success) { return BadRequest(new FailedResponse() { Errors = result.Errors }); } return Ok(new TokenResponse { AccessToken = result.AccessToken, TokenType = result.TokenType }); } [HttpPost("Login")] public async Task<IActionResult> Login(LoginRequest request) { var result = await _userService.LoginAsync(request.UserName, request.Password); if (!result.Success) { return Unauthorized(new FailedResponse() { Errors = result.Errors }); } return Ok(new TokenResponse { AccessToken = result.AccessToken, TokenType = result.TokenType }); }}
service实现
上面已经做好了基本的结构,接下来就是实现UserService中的RegisterAsync和LoginAsync方法了。这里主要用到identity中的UserManager,UserManager封装了很多用户操作的现成方法。
在UserService中先做一个私有方法,根据user创建jwt token;用户注册,登录成功后调用此方法得到token返回即可:
private TokenResult GenerateJwtToken(AppUser user){ var key = Encoding.ASCII.GetBytes(_jwtSettings.SecurityKey); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")), new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()) }), IssuedAt = DateTime.UtcNow, NotBefore = DateTime.UtcNow, Expires = DateTime.UtcNow.Add(_jwtSettings.ExpiresIn), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var jwtTokenHandler = new JwtSecurityTokenHandler(); var securityToken = jwtTokenHandler.CreateToken(tokenDescriptor); var token = jwtTokenHandler.WriteToken(securityToken); return new TokenResult() { AccessToken = token, TokenType = "Bearer" };}
注册方法实现:
public async Task<TokenResult> RegisterAsync(string username, string password, string address){ var existingUser = await _userManager.FindByNameAsync(username); if (existingUser != null) { return new TokenResult() { Errors = new[] {"user already exists!"}, //用户已存在 }; } var newUser = new AppUser() {UserName = username, Address = address}; var isCreated = await _userManager.CreateAsync(newUser, password); if (!isCreated.Succeeded) { return new TokenResult() { Errors = isCreated.Errors.Select(p => p.Description) }; } return GenerateJwtToken(newUser);}
登录方法实现:
public async Task<TokenResult> LoginAsync(string username, string password){ var existingUser = await _userManager.FindByNameAsync(username); if (existingUser == null) { return new TokenResult() { Errors = new[] {"user does not exist!"}, //用户不存在 }; } var isCorrect = await _userManager.CheckPasswordAsync(existingUser, password); if (!isCorrect) { return new TokenResult() { Errors = new[] {"wrong user name or password!"}, //用户名或密码错误 }; } return GenerateJwtToken(existingUser);}
最后,别忘了注册UserService:
services.AddScoped<IUserService, UserService>();
swagger配置
为了方便测试,可以配置一下swagger
NuGet安装包:
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
ConfigureServices:
services.AddSwaggerGen(c =>{ c.SwaggerDoc("v1", new OpenApiInfo { Title = "Sample.Api", Version = "v1", Description = "Sample.Api Swagger Doc" }); c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "Input the JWT like: Bearer {your token}", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, BearerFormat = "JWT", Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, Array.Empty<string>() } });});
app.UseSwagger();app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Sample.Api v1"));
测试一下

随便输入abc进行注册,返回了一些密码规则的错误:

这个规则在注册identity服务时可以配置:
services.AddIdentityCore<AppUser>(options =>{ options.Password.RequireDigit = true; options.Password.RequireLowercase = false; options.Password.RequireUppercase = false; options.Password.RequireNonAlphanumeric = false;}).AddEntityFrameworkStores<AppDbContext>();
identityOptions还支持一些其他配置。
下面注册成功后返回了token:

使用刚刚注册的账号测试登录,也没有问题:

最后
本篇完成了identity的登录,注册,获取token,下一篇将介绍如何使用refresh token。
参考:
asp.net core使用identity+jwt保护你的webapi(二)——获取jwt token的更多相关文章
- asp.net core使用identity+jwt保护你的webapi(一)——identity基础配置
前言 用户模块几乎是每个系统必备的基础功能,如果每次开发一个新项目时都要做个用户模块,确实非常无聊.好在asp.net core给我们提供了Identity,使用起来也是比较方便,如果对用户这块需求不 ...
- asp.net core使用identity+jwt保护你的webapi(三)——refresh token
前言 上一篇已经介绍了identity的注册,登录,获取jwt token,本篇来完成refresh token. 开始 开始之前先说明一下为什么需要refresh token. 虽然jwt toke ...
- Asp.Net Core之Identity应用(上篇)
一.前言 在前面的篇章介绍中,简单介绍了IdentityServer4持久化存储机制相关配置和操作数据,实现了数据迁移,但是未对用户实现持久化操作说明.在总结中我们也提到了, 因为IdentitySe ...
- ASP.NET Core 之 Identity 入门(三)
前言 在上一篇文章中,我们学习了 CookieAuthentication 中间件,本篇的话主要看一下 Identity 本身. 最早2005年 ASP.NET 2.0 的时候开始, Web 应用程序 ...
- [转]ASP.NET Core 之 Identity 入门(三)
本文转自:http://www.cnblogs.com/savorboard/p/aspnetcore-identity3.html 前言 在上一篇文章中,我们学习了 CookieAuthentica ...
- 【分分钟内搭建一个带用户系统的博客程序(一)用户系统】asp.net core的Identity真香,EF真香!
不用不知道,一用香到爆. 老哥是个屌丝前端,但也想写点web应用耍一耍.之前弄过了NodeJs,也弄过JAVA,最近由于写游戏的原因用C#,索性上手一波asp.net core. 这篇博客记录的是,如 ...
- ASP.NET Core 之 Identity 入门(一)
前言 在 ASP.NET Core 中,仍然沿用了 ASP.NET里面的 Identity 组件库,负责对用户的身份进行认证,总体来说的话,没有MVC 5 里面那么复杂,因为在MVC 5里面引入了OW ...
- ASP.NET Core 之 Identity 入门(二)
前言 在 上篇文章 中讲了关于 Identity 需要了解的单词以及相对应的几个知识点,并且知道了Identity处在整个登入流程中的位置,本篇主要是在 .NET 整个认证系统中比较重要的一个环节,就 ...
- [转]ASP.NET Core 之 Identity 入门(二)
本文转自:http://www.cnblogs.com/savorboard/p/aspnetcore-identity2.html 前言 在 上篇文章 中讲了关于 Identity 需要了解的单词以 ...
随机推荐
- c++中的一些会用到的函数
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 int main() { 5 string s ...
- 分享几个下载豆瓣资源的chrome插件
最近chrome终于以4.69%的市场占有率击败firefox成为中国第二大浏览器.(第一当然是争霸宇宙的IE了) 虽然chrome官方应用程序商店有不少豆瓣的辅助插件,但大多没什么用.属于蛋疼插件. ...
- Git使用教程五
基于ssh协议(推荐) 该方式与前面https方式相比,只是影响github对于用户的身份鉴权方式,对于git的具体操作(如提交本地.添加注释.提交远程等操作)没有任何影响. 生成公私钥对指令(需 ...
- MySQL存储结构及SQL分类
MySQL目录结构 bin -- mysql执行程序 docs -- 文档 share - 各国编码信息 data -- 存放mysql 数据文件 * 每个数据库 创建一个同名文件夹,.frm 存放t ...
- 存储系统管理(三)——磁盘配额及lvm逻辑卷管理
Linux是一个多用户的操作系统,系统有很多用户,就必须限制每个用户的保存空间,配额就是来管理用户空间的,配额只是针对与设备而言. 1.新建一个分区 2.格式化分区为xfs文件系统 3.将其以配额的方 ...
- 第17章-x86-64寄存器
不同的CPU都能够解释的机器语言的体系称为指令集架构(ISA,Instruction Set Architecture),也可以称为指令集(instruction set).Intel将x86系列CP ...
- NOIP模拟测试17&18
NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...
- [考试总结]noip模拟46
脑袋确实是不好使了需要回家暴颓治疗 数数数树鼠树 真好玩. 数数 大水题一个,妥妥的签到题目,然后... 我没签上 气展了!!! 其实我还是想麻烦了. 就是我们实际上就是排序之后每一次找头上和尾巴上的 ...
- Linux - 解决使用 apt-get 安装 yum 的时耗报 E: Unable to locate package yum 的错误
问题背景 在 Linux 系统下使用 apt-get 命令安装 yum 库报错 apt-get install yum E: Unable to locate package yum 问题解决 一行命 ...
- Servlet体系结构
一.使用HttpServlet 其中,HttpServlet在重写的service()方法中对http请求的共7中提交方式进行了判断,所以只要我们只要重写对应的请求方式处理逻辑方法 doGet()和d ...