JWT
模拟用户登陆
- nuget安装
Microsoft.AspNetCore.Authentication.JwtBearer
[HttpPost("login")]
[AllowAnonymous] //不用登陆就可以访问,因为是登陆页
public IActionResult login([FromBody] LoginDto loginDto)
{
//1验证用户名密码
...
//2创建JWT
//2.1header
var signingAlgorithm = SecurityAlgorithms.HmacSha256;//定义算法
//2.2payload
var claims = new[] {
//sub用户id
new Claim(JwtRegisteredClaimNames.Sub,"fake_user_id"),
};
//2.3signiture
var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);//将私钥转换成UTF8的字节形式
var signingKey = new SymmetricSecurityKey(secretByte); //先使用非对称算法对私钥进行加密
var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm);//再使用HmacSha256来加密一下非对称加密后的私钥
var token = new JwtSecurityToken(
issuer: _configuration["Authentication:Issuer"], //谁发布的token
audience: _configuration["Authentication:Audience"], //token发布给谁
claims,
notBefore: DateTime.UtcNow,//发布时间
expires: DateTime.UtcNow.AddDays(1),//有效期,1天有效
signingCredentials//数字签名
);
var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);//将token转换成字符串
//3返回jwt
return Ok(tokenStr);
}
启用授权
- program
//注册身份认证服务。参数,默认身份认证类型
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>//配置jwt认证
{
var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]);
opt.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,//验证发布者
ValidIssuer = builder.Configuration["Authentication:Issuer"],
ValidateAudience = true,//验证持有者
ValidAudience = builder.Configuration["Authentication:Audience"],
ValidateLifetime = true,//验证是否过期
//将私钥从配置传入进来进行非对称加密
IssuerSigningKey = new SymmetricSecurityKey(secretByte)
};
});
...
app.UseAuthentication();
app.UseAuthorization();
app.Run();
- 在需要授权的操作方法上增加
[Authorize]
用户角色权限
claim
- 表述用户的身份,说明用户的角色、表示用户所具有的的权限
- 最小不可分割的单位,使用的灵活度高,可以自由组合
- 创建角色
var claims = new[] {
//sub用户id
new Claim(JwtRegisteredClaimNames.Sub,"fake_user_id"),
new Claim(ClaimTypes.Role,"Admin")//添加管理员角色
};
- 启用授权在需要管理员授权的操作方法上增加
[Authorize(Roles ="Admin")]
用户模型与数据库
- nuget安装
Microsoft.AspNetCore.Identity.EntityFrameworkCore
- Program中增加
builder.Services.AddIdentity<IdentityUser,IdentityRole>().AddEntityFrameworkStores<AppDbContext>();
- 数据库context继承IdentityDbContext,
public class AppDbContext:IdentityDbContext<IdentityUser>
用户登陆
private readonly IConfiguration _configuration;
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
public AuthenticateController(IConfiguration configuration, UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
{ _configuration = configuration;
_userManager = userManager;
_signInManager = signInManager;
}
[HttpPost("login")]
[AllowAnonymous]
public async Task< IActionResult> login([FromBody] LoginDto loginDto)
{
//1验证用户名密码
var loginResult = await _signInManager.PasswordSignInAsync(
loginDto.Email,
loginDto.Password,
false,
false
);
if (!loginResult.Succeeded)
{
return BadRequest();
}
var user = await _userManager.FindByNameAsync(loginDto.Email);
var roleNames = await _userManager.GetRolesAsync(user);
//2创建JWT
//2.1header
var signingAlgorithm = SecurityAlgorithms.HmacSha256;//定义算法
//2.2payload
var claims = new List<Claim> {
//sub用户id
new Claim(JwtRegisteredClaimNames.Sub,user.Id),
};
foreach (var roleName in roleNames)
{
var roleClaim = new Claim(ClaimTypes.Role, roleName);
claims.Add(roleClaim);
}
//2.3signiture
var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);//将私钥转换成UTF8的字节形式
var signingKey = new SymmetricSecurityKey(secretByte); //先使用非对称算法对私钥进行加密
var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm);//再使用HmacSha256来验证一下非对称加密后的私钥
var token = new JwtSecurityToken(
issuer: _configuration["Authentication:Issuer"], //谁发布的token
audience: _configuration["Authentication:Audience"], //token发布给谁
claims,
notBefore: DateTime.UtcNow,//发布时间
expires: DateTime.UtcNow.AddDays(1),//有效期,1天有效
signingCredentials//数字签名
);
var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);//将token转换成字符串
//3返回jwt
return Ok(tokenStr);
}
- 操作方法增加
[Authorize(AuthenticationSchemes ="Bearer")]
//identity多角色验证时必须指定
定制用户模型并添加初始化用户数据
- 自定义类
public class ApplictionUser:IdentityUser
{
public string? Address { set; get; }
public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; }
}
- 在context中
// 初始化用户与角色的种子数据
// 1. 更新用户与角色的外键关系
modelBuilder.Entity<ApplictionUser>(b => {
b.HasMany(x => x.UserRoles)
.WithOne()
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
// 2. 添加角色
var adminRoleId = "308660dc-ae51-480f-824d-7dca6714c3e2"; // guid
modelBuilder.Entity<IdentityRole>().HasData(
new IdentityRole
{
Id = adminRoleId,
Name = "Admin",
NormalizedName = "Admin".ToUpper()
}
);
// 3. 添加用户
var adminUserId = "90184155-dee0-40c9-bb1e-b5ed07afc04e";
ApplictionUser adminUser = new ApplictionUser
{
Id = adminUserId,
UserName = "admin@fakexiecheng.com",
NormalizedUserName = "admin@fakexiecheng.com".ToUpper(),
Email = "admin@fakexiecheng.com",
NormalizedEmail = "admin@fakexiecheng.com".ToUpper(),
TwoFactorEnabled = false,
EmailConfirmed = true,
PhoneNumber = "123456789",
PhoneNumberConfirmed = false
};
PasswordHasher<ApplictionUser> ph = new PasswordHasher<ApplictionUser>();
adminUser.PasswordHash = ph.HashPassword(adminUser, "Fake123$");
modelBuilder.Entity<ApplictionUser>().HasData(adminUser);
// 4. 给用户加入管理员权限
// 通过使用 linking table:IdentityUserRole
modelBuilder.Entity<IdentityUserRole<string>>()
.HasData(new IdentityUserRole<string>()
{
RoleId = adminRoleId,
UserId = adminUserId
});