求助:Blazor Server项目基于Microsoft Identity实现授权与角色用户管理
Blazor Server + Microsoft Identity 角色与用户管理实现方案
一、基础配置(未完成的话先做这步)
首先确保项目引入必要依赖并配置Identity:
- 安装NuGet包:
Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore Install-Package Microsoft.EntityFrameworkCore.SqlServer - 修改你的DbContext,继承带角色支持的Identity上下文:
public class AppDbContext : IdentityDbContext<IdentityUser, IdentityRole, string> { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } } - 在
Program.cs中配置Identity与数据库:var builder = WebApplication.CreateBuilder(args); // 配置DbContext builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 添加Identity并启用角色支持 builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<AppDbContext>(); // 添加Blazor与Razor Pages支持(Identity需要Razor Pages处理登录等页面) builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); var app = builder.Build(); // 中间件配置 if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // Identity认证中间件 app.UseAuthentication(); app.UseAuthorization(); app.MapRazorPages(); // 必须添加,否则Identity内置页面无法访问 app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run(); - 执行数据库迁移:
打开Package Manager Console,依次运行:Add-Migration InitializeIdentity Update-Database
二、角色管理页面实现
创建RoleManagement.razor组件,实现角色的增删改查:
@inject RoleManager<IdentityRole> RoleManager @inject ILogger<RoleManagement> Logger @attribute [Authorize(Roles = "Admin")] <div class="container mt-4"> <h3>角色管理</h3> <!-- 创建角色表单 --> <div class="card mb-3"> <div class="card-body"> <h5 class="card-title">创建新角色</h5> <div class="input-group"> <input type="text" class="form-control" placeholder="输入角色名称" @bind="NewRoleName" /> <button class="btn btn-primary" @onclick="CreateRole">创建</button> </div> </div> </div> <!-- 角色列表 --> <table class="table table-striped"> <thead> <tr> <th>角色名称</th> <th>操作</th> </tr> </thead> <tbody> @foreach (var role in Roles) { <tr> <td>@role.Name</td> <td> <button class="btn btn-sm btn-warning" @onclick="() => EditRole(role)">编辑</button> <button class="btn btn-sm btn-danger ms-2" @onclick="() => DeleteRole(role)">删除</button> </td> </tr> } </tbody> </table> <!-- 编辑角色模态框 --> @if (SelectedRole != null) { <div class="modal show d-block" style="background-color: rgba(0,0,0,0.5)"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">编辑角色</h5> <button type="button" class="btn-close" @onclick="() => SelectedRole = null"></button> </div> <div class="modal-body"> <input type="text" class="form-control" @bind="EditedRoleName" /> </div> <div class="modal-footer"> <button class="btn btn-secondary" @onclick="() => SelectedRole = null">取消</button> <button class="btn btn-primary" @onclick="UpdateRole">保存</button> </div> </div> </div> </div> } </div> @code { private List<IdentityRole> Roles = new(); private string NewRoleName = string.Empty; private IdentityRole? SelectedRole; private string EditedRoleName = string.Empty; protected override async Task OnInitializedAsync() { await LoadRoles(); } private async Task LoadRoles() { Roles = (await RoleManager.Roles.ToListAsync()).OrderBy(r => r.Name).ToList(); StateHasChanged(); } private async Task CreateRole() { if (string.IsNullOrWhiteSpace(NewRoleName)) return; var result = await RoleManager.CreateAsync(new IdentityRole(NewRoleName.Trim())); if (result.Succeeded) { NewRoleName = string.Empty; await LoadRoles(); } else { foreach (var error in result.Errors) { Logger.LogError("创建角色失败:{Error}", error.Description); } } } private void EditRole(IdentityRole role) { SelectedRole = role; EditedRoleName = role.Name ?? string.Empty; } private async Task UpdateRole() { if (SelectedRole == null || string.IsNullOrWhiteSpace(EditedRoleName)) return; SelectedRole.Name = EditedRoleName.Trim(); var result = await RoleManager.UpdateAsync(SelectedRole); if (result.Succeeded) { SelectedRole = null; await LoadRoles(); } else { foreach (var error in result.Errors) { Logger.LogError("更新角色失败:{Error}", error.Description); } } } private async Task DeleteRole(IdentityRole role) { var result = await RoleManager.DeleteAsync(role); if (result.Succeeded) { await LoadRoles(); } else { foreach (var error in result.Errors) { Logger.LogError("删除角色失败:{Error}", error.Description); } } } }
三、用户管理与角色分配页面
创建UserManagement.razor组件,实现用户的增删改及角色分配:
@inject UserManager<IdentityUser> UserManager @inject RoleManager<IdentityRole> RoleManager @inject ILogger<UserManagement> Logger @attribute [Authorize(Roles = "Admin")] <div class="container mt-4"> <h3>用户管理</h3> <!-- 创建用户表单 --> <div class="card mb-3"> <div class="card-body"> <h5 class="card-title">创建新用户</h5> <div class="row g-3"> <div class="col-md-6"> <input type="email" class="form-control" placeholder="邮箱" @bind="NewUserEmail" /> </div> <div class="col-md-6"> <input type="password" class="form-control" placeholder="密码" @bind="NewUserPassword" /> </div> <div class="col-12"> <button class="btn btn-primary" @onclick="CreateUser">创建</button> </div> </div> </div> </div> <!-- 用户列表 --> <table class="table table-striped"> <thead> <tr> <th>邮箱</th> <th>用户名</th> <th>邮箱已确认</th> <th>操作</th> </tr> </thead> <tbody> @foreach (var user in Users) { <tr> <td>@user.Email</td> <td>@user.UserName</td> <td>@(user.EmailConfirmed ? "是" : "否")</td> <td> <button class="btn btn-sm btn-info" @onclick="() => OpenRoleAssignmentModal(user)">分配角色</button> <button class="btn btn-sm btn-warning ms-2" @onclick="() => EditUser(user)">编辑</button> <button class="btn btn-sm btn-danger ms-2" @onclick="() => DeleteUser(user)">删除</button> </td> </tr> } </tbody> </table> <!-- 角色分配模态框 --> @if (SelectedUser != null) { <div class="modal show d-block" style="background-color: rgba(0,0,0,0.5)"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">为 @SelectedUser.Email 分配角色</h5> <button type="button" class="btn-close" @onclick="() => SelectedUser = null"></button> </div> <div class="modal-body"> @foreach (var role in AllRoles) { <div class="form-check"> <input class="form-check-input" type="checkbox" id="@role.Id" @bind="SelectedRoles" value="@role.Name" /> <label class="form-check-label" for="@role.Id"> @role.Name </label> </div> } </div> <div class="modal-footer"> <button class="btn btn-secondary" @onclick="() => SelectedUser = null">取消</button> <button class="btn btn-primary" @onclick="SaveUserRoles">保存</button> </div> </div> </div> </div> } </div> @code { private List<IdentityUser> Users = new(); private List<IdentityRole> AllRoles = new(); private string NewUserEmail = string.Empty; private string NewUserPassword = string.Empty; private IdentityUser? SelectedUser; private List<string> SelectedRoles = new(); protected override async Task OnInitializedAsync() { await LoadUsers(); AllRoles = (await RoleManager.Roles.ToListAsync()).OrderBy(r => r.Name).ToList(); } private async Task LoadUsers() { Users = (await UserManager.Users.ToListAsync()).OrderBy(u => u.Email).ToList(); StateHasChanged(); } private async Task CreateUser() { if (string.IsNullOrWhiteSpace(NewUserEmail) || string.IsNullOrWhiteSpace(NewUserPassword)) return; var user = new IdentityUser { UserName = NewUserEmail, Email = NewUserEmail }; var result = await UserManager.CreateAsync(user, NewUserPassword); if (result.Succeeded) { NewUserEmail = string.Empty; NewUserPassword = string.Empty; await LoadUsers(); } else { foreach (var error in result.Errors) { Logger.LogError("创建用户失败:{Error}", error.Description); } } } private async Task OpenRoleAssignmentModal(IdentityUser user) { SelectedUser = user; var currentRoles = await UserManager.GetRolesAsync(user); SelectedRoles = currentRoles.ToList(); } private async Task SaveUserRoles() { if (SelectedUser == null) return; var currentRoles = await UserManager.GetRolesAsync(SelectedUser); var rolesToAdd = SelectedRoles.Except(currentRoles).ToList(); var rolesToRemove = currentRoles.Except(SelectedRoles).ToList(); await UserManager.AddToRolesAsync(SelectedUser, rolesToAdd); await UserManager.RemoveFromRolesAsync(SelectedUser, rolesToRemove); SelectedUser = null; SelectedRoles.Clear(); } private async Task EditUser(IdentityUser user) { // 示例:更新邮箱,可扩展为编辑用户名、重置密码等逻辑 var newEmail = await Prompt("输入新邮箱", user.Email); if (string.IsNullOrWhiteSpace(newEmail)) return; user.Email = newEmail.Trim(); user.UserName = newEmail.Trim(); var result = await UserManager.UpdateAsync(user); if (result.Succeeded) { await LoadUsers(); } else { foreach (var error in result.Errors) { Logger.LogError("更新用户失败:{Error}", error.Description); } } } private async Task DeleteUser(IdentityUser user) { var confirm = await Confirm($"确定要删除用户 {user.Email} 吗?"); if (!confirm) return; var result = await UserManager.DeleteAsync(user); if (result.Succeeded) { await LoadUsers(); } else { foreach (var error in result.Errors) { Logger.LogError("删除用户失败:{Error}", error.Description); } } } // 模拟弹窗方法,实际项目可使用Blazored.Modal等组件 private async Task<string> Prompt(string title, string defaultValue) { return defaultValue; } private async Task<bool> Confirm(string message) { return true; } }
四、权限控制
在Shared/NavMenu.razor中添加管理页面的导航链接,仅管理员可见:
@inject AuthenticationStateProvider AuthenticationStateProvider ... @if (IsAdmin) { <div class="nav-item px-3"> <NavLink class="nav-link" href="role-management"> <span class="oi oi-list-rich" aria-hidden="true"></span> 角色管理 </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="user-management"> <span class="oi oi-people" aria-hidden="true"></span> 用户管理 </NavLink> </div> } @code { private bool IsAdmin { get; set; } protected override async Task OnInitializedAsync() { var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var user = authState.User; IsAdmin = user.IsInRole("Admin"); } }
五、初始化管理员账号
在Program.cs中添加初始化逻辑,创建默认管理员:
// 在app.Run()之前添加 using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>(); var userManager = services.GetRequiredService<UserManager<IdentityUser>>(); // 创建Admin角色 if (!await roleManager.RoleExistsAsync("Admin")) { await roleManager.CreateAsync(new IdentityRole("Admin")); } // 创建管理员用户 var adminEmail = "admin@example.com"; var adminUser = await userManager.FindByEmailAsync(adminEmail); if (adminUser == null) { adminUser = new IdentityUser { UserName = adminEmail, Email = adminEmail, EmailConfirmed = true }; await userManager.CreateAsync(adminUser, "Admin@123"); await userManager.AddToRoleAsync(adminUser, "Admin"); } } app.Run();
内容的提问来源于stack exchange,提问作者meteorra
相关产品推荐
相关产品推荐

