JWT
模拟用户登陆
- nuget安装
Microsoft.AspNetCore.Authentication.JwtBearer
[HttpPost("login")]
[AllowAnonymous] //不用登陆就可以访问,因为是登陆页
publicIActionResultlogin([FromBody] LoginDtologinDto)
{
//1验证用户名密码
...
//2创建JWT
//2.1header
varsigningAlgorithm=SecurityAlgorithms.HmacSha256;//定义算法
//2.2payload
varclaims=new[] {
//sub用户id
newClaim(JwtRegisteredClaimNames.Sub,"fake_user_id"),
};
//2.3signiture
varsecretByte=Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);//将私钥转换成UTF8的字节形式
varsigningKey=newSymmetricSecurityKey(secretByte); //先使用非对称算法对私钥进行加密
varsigningCredentials=newSigningCredentials(signingKey, signingAlgorithm);//再使用HmacSha256来加密一下非对称加密后的私钥
vartoken=newJwtSecurityToken(
issuer: _configuration["Authentication:Issuer"], //谁发布的token
audience: _configuration["Authentication:Audience"], //token发布给谁
claims,
notBefore: DateTime.UtcNow,//发布时间
expires: DateTime.UtcNow.AddDays(1),//有效期,1天有效
signingCredentials//数字签名
);
vartokenStr=newJwtSecurityTokenHandler().WriteToken(token);//将token转换成字符串
//3返回jwt
returnOk(tokenStr);
}
- 启用授权
- program
//注册身份认证服务。参数,默认身份认证类型
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt=>//配置jwt认证
{
varsecretByte=Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]);
opt.TokenValidationParameters=newTokenValidationParameters()
{
ValidateIssuer=true,//验证发布者
ValidIssuer=builder.Configuration["Authentication:Issuer"],
ValidateAudience=true,//验证持有者
ValidAudience=builder.Configuration["Authentication:Audience"],
ValidateLifetime=true,//验证是否过期
//将私钥从配置传入进来进行非对称加密
IssuerSigningKey=newSymmetricSecurityKey(secretByte)
};
});
...
app.UseAuthentication();
app.UseAuthorization();
app.Run();
- 在需要授权的操作方法上增加
[Authorize]
用户角色权限
claim
- 表述用户的身份,说明用户的角色、表示用户所具有的的权限
- 最小不可分割的单位,使用的灵活度高,可以自由组合
- 创建角色
varclaims=new[] {
//sub用户id
newClaim(JwtRegisteredClaimNames.Sub,"fake_user_id"),
newClaim(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>
用户登陆
privatereadonlyIConfiguration_configuration;
privatereadonlyUserManager<IdentityUser>_userManager;
privatereadonlySignInManager<IdentityUser>_signInManager;
publicAuthenticateController(IConfigurationconfiguration, UserManager<IdentityUser>userManager, SignInManager<IdentityUser>signInManager)
{ _configuration=configuration;
_userManager=userManager;
_signInManager=signInManager;
}
[HttpPost("login")]
[AllowAnonymous]
publicasyncTask<IActionResult>login([FromBody] LoginDtologinDto)
{
//1验证用户名密码
varloginResult=await_signInManager.PasswordSignInAsync(
loginDto.Email,
loginDto.Password,
false,
false
);
if (!loginResult.Succeeded)
{
returnBadRequest();
}
varuser=await_userManager.FindByNameAsync(loginDto.Email);
varroleNames=await_userManager.GetRolesAsync(user);
//2创建JWT
//2.1header
varsigningAlgorithm=SecurityAlgorithms.HmacSha256;//定义算法
//2.2payload
varclaims=newList<Claim> {
//sub用户id
newClaim(JwtRegisteredClaimNames.Sub,user.Id),
};
foreach (varroleNameinroleNames)
{
varroleClaim=newClaim(ClaimTypes.Role, roleName);
claims.Add(roleClaim);
}
//2.3signiture
varsecretByte=Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);//将私钥转换成UTF8的字节形式
varsigningKey=newSymmetricSecurityKey(secretByte); //先使用非对称算法对私钥进行加密
varsigningCredentials=newSigningCredentials(signingKey, signingAlgorithm);//再使用HmacSha256来验证一下非对称加密后的私钥
vartoken=newJwtSecurityToken(
issuer: _configuration["Authentication:Issuer"], //谁发布的token
audience: _configuration["Authentication:Audience"], //token发布给谁
claims,
notBefore: DateTime.UtcNow,//发布时间
expires: DateTime.UtcNow.AddDays(1),//有效期,1天有效
signingCredentials//数字签名
);
vartokenStr=newJwtSecurityTokenHandler().WriteToken(token);//将token转换成字符串
//3返回jwt
returnOk(tokenStr);
}
- 操作方法增加
[Authorize(AuthenticationSchemes ="Bearer")]
//identity多角色验证时必须指定
定制用户模型并添加初始化用户数据
- 自定义类
publicclassApplictionUser:IdentityUser
{
publicstring?Address { set; get; }
publicvirtualICollection<IdentityUserRole<string>>UserRoles { get; set; }
}
- 在context中
// 初始化用户与角色的种子数据
// 1. 更新用户与角色的外键关系
modelBuilder.Entity<ApplictionUser>(b=> {
b.HasMany(x=>x.UserRoles)
.WithOne()
.HasForeignKey(ur=>ur.UserId)
.IsRequired();
});
// 2. 添加角色
varadminRoleId="308660dc-ae51-480f-824d-7dca6714c3e2"; // guid
modelBuilder.Entity<IdentityRole>().HasData(
newIdentityRole
{
Id=adminRoleId,
Name="Admin",
NormalizedName="Admin".ToUpper()
}
);
// 3. 添加用户
varadminUserId="90184155-dee0-40c9-bb1e-b5ed07afc04e";
ApplictionUseradminUser=newApplictionUser
{
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=newPasswordHasher<ApplictionUser>();
adminUser.PasswordHash=ph.HashPassword(adminUser, "Fake123$");
modelBuilder.Entity<ApplictionUser>().HasData(adminUser);
// 4. 给用户加入管理员权限
// 通过使用 linking table:IdentityUserRole
modelBuilder.Entity<IdentityUserRole<string>>()
.HasData(newIdentityUserRole<string>()
{
RoleId=adminRoleId,
UserId=adminUserId
});