前言

上一篇已经介绍了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中的RegisterAsyncLoginAsync方法了。这里主要用到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 | Microsoft Docs[1]

Mohamad Lawand - DEV Community[2]

参考资料

[1]

ASP.NET Core 简介 Identity | Microsoft Docs: https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/identity?view=aspnetcore-5.0&tabs=visual-studio

[2]

Mohamad Lawand - DEV Community: https://dev.to/moe23/comments

使用identity+jwt保护你的webapi(二)——获取jwt token相关推荐

  1. 使用identity+jwt保护你的webapi(三)——refresh token

    前言 上一篇已经介绍了identity的注册,登录,获取jwt token,本篇来完成refresh token. 开始 开始之前先说明一下为什么需要refresh token. 虽然jwt toke ...

  2. 使用identity+jwt保护你的webapi(一)——identity基础配置

    前言 用户模块几乎是每个系统必备的基础功能,如果每次开发一个新项目时都要做个用户模块,确实非常无聊.好在asp.net core给我们提供了Identity,使用起来也是比较方便,如果对用户这块需求不 ...

  3. 《深入理解 Spring Cloud 与微服务构建》第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统 文章目录 <深入理解 Spring Cl ...

  4. ASP.NET Core WebAPI中使用JWT Bearer认证和授权

    为什么是 JWT Bearer ASP.NET Core 在 Microsoft.AspNetCore.Authentication 下实现了一系列认证, 包含 Cookie, JwtBearer,  ...

  5. .NET core3.0 使用Jwt保护api

    摘要: 本文演示如何向有效用户提供jwt,以及如何在webapi中使用该token通过JwtBearerMiddleware中间件对用户进行身份认证. 认证和授权区别? 首先我们要弄清楚认证(Auth ...

  6. ASP.NET Core Web Api之JWT VS Session VS Cookie(二)

    本文我们来探讨下JWT VS Session的问题,我们可直接抛出问题:使用客户端存储的JWT比服务端维持Session更好吗? 既然要比较JWT VS Session,那我们就得知道为何需要JWT和 ...

  7. 小程序 jwt_使用JWT保护应用程序安全的简介

    小程序 jwt JSON Web Tokens have become the favorite choice among modern developers when implementing us ...

  8. jwt配置 restful_SpringBoot实现JWT保护前后端分离RESTful API

    本文将用不到100行Java代码, 教你如何在Spring Boot里面用JWT保护RESTful api. 登录前 登录之后即可得到正确结果 登陆后 1. 什么是JWT 了解JWT的同学可以跳过这一 ...

  9. webapi随机调用_BeetleX之webapi验证插件JWT集成

    对于webapi服务应用很多时候需要制订访问限制,在前面的章节也讲述了组件如何制订控制器访问控制:但到了实际应用要自己去编写还是比较麻烦.为了让访问控制更方便组件实现基于JWT的控制器访问控制组件Be ...

最新文章

  1. torch.nn.softmax()
  2. Windows7下如何设置MyEclipse2014字体大小
  3. 微信可以远程控制电脑吗_用微信就能远程控制电脑,这款神器有些厉害
  4. Json数组转Map
  5. allegro 自定义快捷键
  6. 创建一维数组,存储班级中10位同学的年龄信息,并求出班级同学的平均年龄。找出班级中的最小年龄和最大年龄。(冒泡排序)
  7. 盲修瞎练路漫漫,名师点化三日成[转]
  8. 2017年中国大数据发展趋势和展望解读(上)
  9. hiredis-vip
  10. Cache poisoning
  11. Java Web学习笔记 3 深入Servlet技术
  12. 11.2. Yate Client
  13. matlab-采用For循环,将每次计算得到的矩阵,依次放进一个新的矩阵
  14. [BZOJ2844]albus就是要第一个出场
  15. linux安装appt服务,centos 64位linux系统下安装appt命令
  16. 手把手教你更改maven镜像源
  17. 关于STARMAC旋翼机的计算系统组成分析
  18. 案例分享,Appium+Python实现APP启动页跳转到首页!
  19. php中 复合主键的作用,php – Laravel – 使用复合主键加入表
  20. RPC304A POE系统四通道PSE控制芯片,POE Controller,PSE Controller ,主要PIN IP804/IP808,TPS28361等芯片

热门文章

  1. 这段代码什么意思啊?
  2. 花开的声音 - 张靓颖
  3. Matplotlib学习---用matplotlib画误差线(errorbar)
  4. MyBatis 分页插件 PageHelper
  5. turtle库基础练习
  6. 信息安全系统设计基础第七周学习总结
  7. Android:源码环境编译自定义的APP到ROM(System Image)中
  8. C#编程中的66个好习惯,你有多少个?(转)
  9. 了解jQuery技巧来提高你的代码
  10. mysql学习笔记之mysqlparameter(摘)