跳到主要内容

IGeekFan.AspNetCore.Identity.FreeSql

ASP.NET Core Identity 的 FreeSql 存储实现。

功能概览

功能说明
Identity 存储ASP.NET Core Identity FreeSql 实现
多数据库支持 MySQL、PostgreSQL、SQLite 等

安装

dotnet add package IGeekFan.AspNetCore.Identity.FreeSql
dotnet add package FreeSql.Provider.MySqlConnector # 或其他 Provider

快速开始

场景:用户注册登录

1. 定义用户和角色

public class AppUser : IdentityUser<Guid>
{
public string FirstName { get; set; } = default!;
public string LastName { get; set; } = default!;
}

public class AppRole : IdentityRole<Guid>
{
}

2. 创建 DbContext

public class AppIdentityDbContext : IdentityDbContext<AppUser, AppRole, Guid>
{
public AppIdentityDbContext(
IOptions<IdentityOptions> identityOptions,
IFreeSql fsql,
DbContextOptions options)
: base(identityOptions.Value, fsql, options)
{
}

protected override void OnModelCreating(ICodeFirst codefirst)
{
base.OnModelCreating(codefirst);
codefirst.ApplyConfiguration(new AppUserConfiguration());
}
}

3. Fluent API 配置

public class AppUserConfiguration : IEntityTypeConfiguration<AppUser>
{
public void Configure(EfCoreTableFluent<AppUser> builder)
{
builder.Property(x => x.FirstName).HasMaxLength(50);
builder.Property(x => x.LastName).HasMaxLength(50);
}
}

4. 注册服务

// 扩展方法
public static IServiceCollection AddFreeSqlIdentity(
this IServiceCollection services, IConfiguration configuration)
{
// 注册 FreeSql
services.AddSingleton<IFreeSql>(sp =>
{
var fsql = new FreeSqlBuilder()
.UseConnectionString(DataType.MySql, configuration["ConnectionStrings:MySql"])
.UseAutoSyncStructure(true)
.Build();

fsql.GlobalFilter.Apply<ISoftDelete>("IsDeleted", a => a.IsDeleted == false);
return fsql;
});

services.AddFreeRepository();
services.AddScoped<UnitOfWorkManager>();

// 注册 DbContext
services.AddFreeDbContext<AppIdentityDbContext>(options => options
.UseOptions(new DbContextOptions { EnableCascadeSave = true }));

// 配置 Identity
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });

services.AddIdentityCore<AppUser>(o =>
{
o.SignIn.RequireConfirmedEmail = false;
o.Stores.MaxLengthForKeys = 128;
})
.AddRoles<AppRole>()
.AddSignInManager()
.AddFreeSqlStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();

return services;
}

5. Program.cs

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFreeSqlIdentity(builder.Configuration);

var app = builder.Build();

// 同步表结构
using (var scope = app.Services.CreateScope())
{
var fsql = scope.ServiceProvider.GetRequiredService<IFreeSql>();
fsql.CodeFirst.SyncStructure(typeof(AppUser), typeof(AppRole));
}

app.Run();

API 示例

注册用户

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly UserManager<AppUser> _userManager;

public AuthController(UserManager<AppUser> userManager) => _userManager = userManager;

[HttpPost("register")]
public async Task<IActionResult> Register(RegisterRequest request)
{
var user = new AppUser
{
FirstName = request.FirstName,
LastName = request.LastName,
EmailConfirmed = true
};

await _userManager.SetUserNameAsync(user, request.Email, CancellationToken.None);
await ((IUserEmailStore<AppUser>)_userManager).SetEmailAsync(user, request.Email, CancellationToken.None);

var result = await _userManager.CreateAsync(user, request.Password);
return result.Succeeded ? Ok() : BadRequest(result.Errors);
}
}

public record RegisterRequest(string FirstName, string LastName, string Email, string Password);

登录

[HttpPost("login")]
public async Task<IActionResult> Login(LoginRequest request)
{
var result = await _signInManager.PasswordSignInAsync(
request.Email, request.Password, request.RememberMe, false);

if (result.Succeeded)
{
var user = await _userManager.FindByEmailAsync(request.Email);
var token = Guid.NewGuid().ToString(); // 生成 Token
return Ok(token);
}

return Unauthorized();
}

public record LoginRequest(string Email, string Password, bool RememberMe);

数据库配置

{
"ConnectionStrings": {
"MySql": "Data Source=localhost;Port=3306;User ID=root;Password=root;Initial Catalog=mydb;Charset=utf8mb4"
}
}

故障排查

问题解决方案
表未创建确保调用 CodeFirst.SyncStructure
密码验证失败检查 IdentityOptions 配置
登录失败检查用户是否存在、密码是否正确

相关文档