本文章是我听B站杨中科的所做的笔记
杨中科B站视频链接:.NET 6教程,.Net Core 2022视频教程,杨中科主讲_哔哩哔哩_bilibili
Identity框架入门
Authentication与Authorization
1、Authentication对访问者的用户身份进行验证,“用户是否登录成功”
2、Authorization验证访问者的用户身份是否有对资源访问的访问权限,“用户是否有权限访问这个地址”。
标识(Identity)框架
1、标识(Identity)框架:采用基于角色的访问控制(Role-Based Access Control,简称RBAC)策略,内置了对用户、角色等表的管理以及相关的接口,支持外部登录、2FA等
2、标识框架使用EF Core对数据库进行操作,因此标识框架支持几乎所有的数据库
Identity框架的使用
1、IdentityUser<TKey>、IdentityRole<TKey>,TKey代表主键的类型。我们一般编写继承自IdentityUser<TKey>、IdentityRole<TKey>等的自定义类,可以增加自定义属性
2、NuGet安装:Microsoft.AspNetCore.Identity.EntityFrameworkCore。
3、创建继承自IdentityDbContext的类
4、可以通过IdDbContext类来操作数据库,不过框架中提供了RoleManager、UserManager等类来简化数据库的操作
5、部分方法的返回值为Task<IdentityResult>类型,查看、讲解IdentityResult类型定义
6、向依赖注入容器中注册标识框架相关的服务
IServiceCollection services = builder.Services;
services.AddDbContext<IdDbContext>(opt => {
string connStr = builder.Configuration.GetConnectionString("Default");
opt.UseSqlServer(connStr);});
services.AddDataProtection();
services.AddIdentityCore<User>(options =>{ //注意不是AddIdentity
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequiredLength = 6;
options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider; });
var idBuilder = new IdentityBuilder(typeof(User), typeof(Role), services);
idBuilder.AddEntityFrameworkStores<IdDbContext>()
.AddDefaultTokenProviders().AddRoleManager<RoleManager<Role>>()
.AddUserManager<UserManager<User>>();
7、执行Add-Migration、Update-Database等命令执行EF Core的数据库迁移
8、通过RoleManager、UserManager等来进行数据操作。比如创建角色、创建用户
bool roleExists = await roleManager.RoleExistsAsync("admin");
if (!roleExists)
{
Role role = new Role { Name="Admin"};
var r = await roleManager.CreateAsync(role);
if (!r.Succeeded) return BadRequest(r.Errors);
}
User user = await this.userManager.FindByNameAsync("yzk");
if (user == null)
{
user=new User{UserName="yzk",Email="yangzhongke8@gmail.com",EmailConfirmed=true};
var r = await userManager.CreateAsync(user, "123456");
if (!r.Succeeded) return BadRequest(r.Errors);
r = await userManager.AddToRoleAsync(user, "admin");
}
9、检查登录用户信息
string userName = req.UserName;
string password = req.Password;
var user = await userManager.FindByNameAsync(userName);
if (user == null)
return NotFound($"用户名不存在{userName}");
if (await userManager.IsLockedOutAsync(user))
return BadRequest("LockedOut");
var success = await userManager.CheckPasswordAsync(user, password);
if (success) {
await userManager.ResetAccessFailedCountAsync(user);
return Ok("Success");
}
else await userManager.AccessFailedAsync(user);
Identity框架实现密码的重置
重置密码流程
1、生成重置的Token
2、Token发给客户(邮件、短信),形式:链接、验证码等
3、根据Token完成密码的重置
发送重置密码的请求
var user = await userManager.FindByEmailAsync(email);
string token = await userManager.GeneratePasswordResetTokenAsync(user);
logger.LogInformation($"向邮箱{user.Email}发送Token={token}");
完成重置密码
await userManager.ResetPasswordAsync(user, token, password);
代替Session的JWT是什么
Session的缺点
1、对于分布式集群环境,Session数据保存在服务器内存中就不合适了,应该放到一个中心状态服务器上。ASP.NET Core支持Session采用Redis、Memcacheed.
2、中心状态服务器有性能问题
JWT(Json Web Token)
1、JWT把登录信息(也称作令牌)保存在客户端
2、为了防止客户端的数据造假,保存在客户端的令牌经过了签名处理,而签名的密钥只有服务器端才知道,每次服务器端接收到客户端提交过来的令牌的时候都要检查一下签名。
3、基于JWT如何实现“登录”
JWT的基本使用
生成JWT令牌
1、NuGet:System.IdentityModel.Token.Jwt
2、var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.NameIdentifier, "6"));
claims.Add(new Claim(ClaimTypes.Name, "yzk"));
claims.Add(n