Asp.Net Core IdentityServer4
Asp.Net Core IdentityServer4
(1)Authentication与Authorization
- Authentication对访问者的用户身份进行验证,“用户是否登录成功”。
- Authorization验证访问者的用户身份是否有对资源访问的访问权限,“用户是否有权限访问这个地址”。
(2)Identity框架
- 采用基于角色的访问控制(Role-Based Access Control,简称RBAC)策略,内置了对用户、角色等表的管理及相关的接口,支持外部登录、2FA等
- 标识框架使用EFCore对数据库进行操作,因此标识框架支持几乎所有数据库
(3)Identity框架使用
- NuGet安装Microsoft.AspNetCore.Identity.EntityFrameworkCore等相关包
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
- 创建继承自IdentityDbContext的类
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
public class IdDbContext : IdentityDbContext<User, Role, long>
{
public IdDbContext(DbContextOptions<IdDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
- IdentityUser
、IdentityRole ,TKey代表主键的类型
Role
public class Role : IdentityRole<long>
{
}
User
public class User : IdentityUser<long>
{
}
- Program注入Identity服务
//数据保护
builder.Services.AddDataProtection();
//Identity
builder.Services.AddIdentityCore<User>(options =>
{
//指示密码是否必须包含数字
options.Password.RequireDigit = false;
//指示密码是否必须包含小写ASCII字符。
options.Password.RequireLowercase = false;
//指示密码是否必须包含非字母数字字符。
options.Password.RequireNonAlphanumeric = false;
//指示密码是否必须包含大写ASCII字符
options.Password.RequireUppercase = false;
//获取或设置密码必须的最小长度。 默认为6。
options.Password.RequiredLength = 6;
//用于生成密码重置邮件中使用的令牌。
options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
//获取或设置用于生成帐户确认中使用的令牌的令牌提供程序
options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
});
//注入RoleManager UserManager
var idBuilder = new IdentityBuilder(typeof(User), typeof(Role), builder.Services);
idBuilder.AddEntityFrameworkStores<IdDbContext>()
.AddDefaultTokenProviders()
.AddRoleManager<RoleManager<Role>>()
.AddUserManager<UserManager<User>>();
- 创建IDesignTimeDbContextFactory用来迁移,sqlserver和mysql都可以,这里使用mysql
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
class MyDesignTimeDbContextFactory : IDesignTimeDbContextFactory<IdDbContext>
{
public IdDbContext CreateDbContext(string[] args)
{
DbContextOptionsBuilder<IdDbContext> builder = new();
//环境变量获取方式
//string connStr = Environment.GetEnvironmentVariable("ConnectionStrings:Default");
//mysql
string connStr = @"Server=localhost; Port=3306;Stmt=; Database=identitydb; Uid=root; Pwd=root;";
var serverVersion = new MySqlServerVersion(new Version(5, 7, 28));
builder.UseMySql(connStr, serverVersion);
//sqlServer
//string connStr = @"Data Source=.;Initial Catalog=YZKStudy;Persist Security Info=True;User ID=sa;Password=123456";
//builder.UseSqlServer(connStr);
//string connStr = "Data Source=.;Initial Catalog=Identitydb;Persist Security Info=True;User ID=sa;Password=123456";
//builder.UseSqlServer(connStr);
return new IdDbContext(builder.Options);
}
}
- 执行Add-Migration、Update-Database命令执行EF Core的数据库迁移。
- 可以通过IdDbContext类来操作数据库,不过框架中提供了RoleManager、UserManager等类来简化对数据库的操作
LoginController
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace IdentityDemo.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class LoginController : ControllerBase
{
private readonly ILogger<LoginController> logger;
private readonly RoleManager<Role> roleManager;
private readonly UserManager<User> userManager;
public LoginController(ILogger<LoginController> logger,
RoleManager<Role> roleManager, UserManager<User> userManager)
{
this.logger = logger;
this.roleManager = roleManager;
this.userManager = userManager;
}
/// <summary>
/// 登录
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost]
public async Task<ActionResult> Login(LoginRequest req)
{
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)
{
return Ok("Success");
}
else
{
var r = await userManager.AccessFailedAsync(user);
if (!r.Succeeded)
{
return BadRequest("AccessFailed failed");
}
return BadRequest("Failed");
}
}
/// <summary>
/// 发送验证码
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> SendResetPasswordToken(
SendResetPasswordTokenRequest req)
{
string email = req.Email;
var user = await userManager.FindByEmailAsync(email);
if (user == null)
{
return NotFound($"邮箱不存在{email}");
}
string token = await userManager.GeneratePasswordResetTokenAsync(user);
logger.LogInformation($"向邮箱{user.Email}发送Token={token}");
return Ok();
}
[HttpPost]
public async Task<IActionResult> ResetPassword(ResetPasswordRequest req)
{
var user = await userManager.FindByNameAsync(req.UserName);
var res = await userManager.ResetPasswordAsync(user, req.Token, req.Password);
if (!res.Succeeded)
{
return BadRequest("重置失败");
}
else
{
return Ok("重置成功");
}
}
}
public record LoginRequest(string UserName, string Password);
public record ResetPasswordRequest(string UserName, string Token, string Password);
public record SendResetPasswordTokenRequest(string Email);
}
UserController
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace IdentityDemo.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly ILogger<UserController> logger;
private readonly RoleManager<Role> roleManager;
private readonly UserManager<User> userManager;
public UserController(ILogger<UserController> logger, RoleManager<Role> roleManager, UserManager<User> userManager)
{
this.logger = logger;
this.roleManager = roleManager;
this.userManager = userManager;
}
/// <summary>
/// 创建peng用户 密码123456
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<ActionResult> CreateUserRole()
{
bool roleExists = await roleManager.RoleExistsAsync("admin");
//如果不存在 创建admin角色
if (!roleExists)
{
Role role = new Role { Name = "Admin" };
var r = await roleManager.CreateAsync(role);
if (!r.Succeeded)
{
return BadRequest(r.Errors);
}
}
//查找peng的用户
User user = await this.userManager.FindByNameAsync("peng");
//不存在就创建peng用户
if (user == null)
{
user = new User { UserName = "peng", Email = "123@163.com", EmailConfirmed = true };
//创建peng用户
var r = await userManager.CreateAsync(user, "123456");
if (!r.Succeeded)
{
return BadRequest(r.Errors);
}
//peng分配admin角色
r = await userManager.AddToRoleAsync(user, "admin");
if (!r.Succeeded)
{
return BadRequest(r.Errors);
}
}
return Ok();
}
}
}
分类:
IdentityServer4
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!