.Net5.0 WebApi 注册登录以及基于JWT的简单身份认证与授权

  • A+
所属分类:.NET技术
摘要

powershell中执行或者使用Visual Studio 2019 默认的模板已经配置了Swagger中间件,启用Swagger的验证功能,ConfigureServices方法中增加

  • 新建一个API的项目

powershell中执行

dotnet new webapi

或者使用Visual Studio 2019

 .Net5.0 WebApi 注册登录以及基于JWT的简单身份认证与授权.Net5.0 WebApi 注册登录以及基于JWT的简单身份认证与授权

默认的模板已经配置了Swagger中间件,启用Swagger的验证功能,ConfigureServices方法中增加

services.AddSwaggerGen(c => {    ...     c.AddSecurityRequirement(new OpenApiSecurityRequirement     {         {             new OpenApiSecurityScheme             {                 Reference = new OpenApiReference                 {                     Id = "Bearer",                     Type = ReferenceType.SecurityScheme                 }             },              Array.Empty<string>()          }      });     c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme     {         Description = "Please enter into field the word 'Bearer' followed by a space and the JWT value",         Name = "Authorization",         In = ParameterLocation.Header,         Type = SecuritySchemeType.ApiKey     }); });

 

 

  • 配置身份认证服务
  1. Configure方法

app.UseAuthorization()之前增加app.UseAuthentication();

  1. ConfigureServices方法

增加

services.AddAuthorization(options => {     options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>     {         policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);         policy.RequireClaim(ClaimTypes.Name);         policy.RequireRole(ClaimTypes.Role);     }); }); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)     .AddJwtBearer(options =>     {         options.Events = new JwtBearerEvents         {             OnTokenValidated = async context =>             {                 var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>();                 var name = context.Principal.Identity.Name;                 var user = await userService.GetByNameAysnc(name);                 if (user == null)                 {                     context.Fail("Unauthorized");                 }             }         };         options.TokenValidationParameters =             new TokenValidationParameters             {                 ValidateAudience = false,                 ValidateIssuer = false,                 ValidateActor = false,                 ValidateLifetime = true,                 IssuerSigningKey = UsersController.SecurityKey             };     });

 

 

 

  • 使用mssql数据库
  1. 引入依赖
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0">   <PrivateAssets>all</PrivateAssets>   <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0">   <PrivateAssets>all</PrivateAssets>   <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference>

 

  1. ConfigureServices方法
var sqlConnection = Configuration.GetConnectionString("SqlServerConnection"); services.AddDbContext<WebAPIDBContent>(option => option.UseSqlServer(sqlConnection));

 

  • 配置数据库
  1. 创建表

 

public class User {     [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]     public int Id { get; set; }     [Required, MaxLength(64)]     public string UserName { get; set; }     [Required, MaxLength(64)]     public byte[] PasswordHash { get; set; }     [Required, MaxLength(128)]     public byte[] PasswordSalt { get; set; }     [Required, MaxLength(20)]     public string Phone { get; set; }     [Required, MaxLength(20)]     public string UserType { get; set; } }

 

  1. 创建数据库
public class WebAPIDBContent : DbContext {     public WebAPIDBContent(DbContextOptions<WebAPIDBContent> options) : base(options)     {     }      public DbSet<User> Users { get; set; } }

  1. .迁移数据库

数据库连接配置:appsettings.json中增加

  "ConnectionStrings": {     "SqlServerConnection": "Server=(localdb)\mssqllocaldb;Database=WedAPIServer;Trusted_Connection=True;MultipleActiveResultSets=true"   },

 程序包管理器控制台中执行

Add-Migration InitialCreate Update-Database

  • 增加用户控制器
[Authorize(Roles = "Admin")] [ApiController] [Route("[controller]")] public class UsersController : ControllerBase {     public static JwtSecurityTokenHandler JwtTokenHandler = new JwtSecurityTokenHandler();     public static SymmetricSecurityKey SecurityKey = new SymmetricSecurityKey(Guid.NewGuid().ToByteArray());      private IUserService _userService;     private IMapper _mapper;     private IActionContextAccessor _accessor;     private readonly ILogger<UsersController> _logger;       public UsersController(         ILogger<UsersController> logger,         IUserService userService,         IMapper mapper,         IActionContextAccessor httpContextAccessor)     {         _logger = logger;         _userService = userService;         _mapper = mapper;         _accessor = httpContextAccessor;     }      [AllowAnonymous]     [HttpPost("authenticate")]     public async Task<IActionResult> Authenticate(UserDto userDto)     {         _logger.LogInformation($"Authenticate {userDto.Username}@{userDto.Password}");         var user = await _userService.AuthenticateAysnc(userDto.Username, userDto.Password);          if (user == null)             return BadRequest(new { message = "Username or password is incorrect" });          var claims = new[] { new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.Role, user.UserType) };         var credentials = new SigningCredentials(SecurityKey, SecurityAlgorithms.HmacSha256);         var token = new JwtSecurityToken("WebAPIServer", "WebAPIClients", claims, expires: DateTime.Now.AddDays(1), signingCredentials: credentials);         var tokenString = JwtTokenHandler.WriteToken(token);         return Ok(new         {             Type = "Bearer",             Token = tokenString         });     }      [AllowAnonymous]     [HttpPost("register")]     public async Task<IActionResult> Register(UserDto userDto)     {         _logger.LogInformation($"Register {userDto.Username}@{userDto.Password}@{userDto.Phone}");         var user = _mapper.Map<User>(userDto);         try         {             var _user = await _userService.CreateAysnc(user, userDto.Password);             return Ok(_mapper.Map<UserDto>(_user));         }         catch (AppException ex)         {             _logger.LogWarning($"Register AppException"+ ex.Message);             return BadRequest(new { message = ex.Message });         }     }      [HttpGet]     public async Task<IActionResult> GetAll()     {         _logger.LogInformation($"GetAll");         var users = await _userService.GetAllAysnc();     var userDtos = _mapper.Map<List<UserDto>>(users);     return Ok(userDtos); }  [HttpGet("{id}")] public async Task<IActionResult> GetById(int id) {     _logger.LogInformation($"GetById {id}");     var user = await _userService.GetByIdAysnc(id);     var userDto = _mapper.Map<UserDto>(user);     return Ok(userDto); }  [HttpPut("{id}")] public async Task<IActionResult> Update(int id, UserDto userDto) {     _logger.LogInformation($"Update {id} {userDto.Username}@{userDto.Password}@{userDto.Phone}");     var user = _mapper.Map<User>(userDto);     user.Id = id;     try     {         await _userService.UpdateAysnc(user, userDto.Password);         return Ok();     }     catch (AppException ex)     {         return BadRequest(new { message = ex.Message });     } }  [HttpDelete("{id}")] public async Task<IActionResult> Delete(int id) {     _logger.LogInformation($"Delete {id}");     await _userService.DeleteAysnc(id);     return Ok(); }

  • 测试
  1. 注册一个管理员账户

.Net5.0 WebApi 注册登录以及基于JWT的简单身份认证与授权

  1. 登录,获取token

.Net5.0 WebApi 注册登录以及基于JWT的简单身份认证与授权

  1. 点击右上角的Authorize填写token

.Net5.0 WebApi 注册登录以及基于JWT的简单身份认证与授权

  1. 成功调用其他API

.Net5.0 WebApi 注册登录以及基于JWT的简单身份认证与授权

 调用Get/Users API 时,如果未登录,返回401,如果登录的不是管理员账户(用户类型Admin),返回403

 项目地址:https://gitee.com/ALittleDruid/WebAPIServer