基于 BootstrapBlazor + ASP.NET Core Identity 实现,分 5 大块:环境配置、注册页面、登录页面、授权拦截、后台新增数据自动绑定当前登录用户。
一、前置准备(项目开启 Identity)
1.NuGet 安装包
<PackageReference Include="BootstrapBlazor" Version="最新版" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
2.Program.cs 注册服务
var builder = WebApplication.CreateBuilder(args);
// 1. 添加DbContext + Identity
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
// Identity 用户表,扩展自定义字段
builder.Services.AddDefaultIdentity<AppUser>(options =>
{
// 密码规则
options.Password.RequireDigit = false;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
})
.AddEntityFrameworkStores<AppDbContext>();
// 2. BootstrapBlazor
builder.Services.AddBootstrapBlazor();
// 3. Blazor 组件
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
// 认证授权中间件顺序不能乱
app.UseStaticFiles();
app.UseAuthentication(); // 登录Cookie
app.UseAuthorization(); // 权限校验
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
自定义用户实体 AppUser.cs
扩展需要的字段(手机号、昵称等),继承 IdentityUser
using Microsoft.AspNetCore.Identity;
public class AppUser : IdentityUser
{
// 可自定义扩展字段
public string NickName { get; set; } = "";
}
数据库上下文 AppDbContext.cs
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
public class AppDbContext : IdentityDbContext<AppUser>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
// 业务表示例(后台需要保存的数据表)
public DbSet<Product> Products { get; set; }
}
// 业务实体示例(每条数据记录创建人用户名)
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public decimal Price { get; set; }
// 关联登录用户名
public string CreateUserName { get; set; } = "";
public DateTime CreateTime { get; set; } = DateTime.Now;
}
迁移数据库
Add-Migration InitIdentity
Update-Database
自动生成:AspNetUsers、登录 / 角色相关表 + 业务 Product 表
二、共享工具类:获取当前登录用户
新建 AuthHelper.cs 全局获取登录用户名、ID
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
public static class AuthHelper
{
/// 获取当前登录用户名
public static async Task<string> GetUserNameAsync(AuthenticationStateProvider auth)
{
var state = await auth.GetAuthenticationStateAsync();
var user = state.User;
if (!user.Identity.IsAuthenticated)
return "";
return user.Identity.Name ?? "";
}
/// 获取UserId
public static async Task<string> GetUserIdAsync(AuthenticationStateProvider auth)
{
var state = await auth.GetAuthenticationStateAsync();
var user = state.User;
return user.FindFirstValue(ClaimTypes.NameIdentifier) ?? "";
}
/// 判断是否登录
public static async Task<bool> IsLoginAsync(AuthenticationStateProvider auth)
{
var state = await auth.GetAuthenticationStateAsync();
return state.User.Identity.IsAuthenticated;
}
}
三、注册页面 Register.razor(BootstrapBlazor 表单)
路径 Pages/Account/Register.razor
@page "/account/register"@inject UserManager
@inject SignInManager
@inject NavigationManager Nav
@inject ToastService Toast
<Body>
<EditForm Model="@model" OnValidSubmit="@RegisterSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<FormInput @bind-Value="model.UserName" Label="用户名" Placeholder="请输入用户名" />
<FormInput @bind-Value="model.Email" Label="邮箱" Placeholder="请输入邮箱" InputType="InputType.Email" />
<FormInput @bind-Value="model.Password" Label="密码" Placeholder="至少6位" InputType="InputType.Password" />
<FormInput @bind-Value="model.ConfirmPwd" Label="确认密码" InputType="InputType.Password" />
<Button Type="ButtonType.Submit" Color="Color.Primary" Class="mt-3">注册</Button>
<a href="/account/login" class="ms-3">已有账号去登录</a>
</EditForm>
</Body>@code {
private RegisterModel model = new();
private async Task RegisterSubmit()
{
if (model.Password != model.ConfirmPwd)
{
await Toast.Error("两次密码不一致");
return;
}
var user = new AppUser
{
UserName = model.UserName,
Email = model.Email,
NickName = model.UserName
};
// 创建用户
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// 注册后自动登录
await SignInManager.SignInAsync(user, false);
await Toast.Success("注册成功");
Nav.NavigateTo("/");
}
else
{
var msg = string.Join(";", result.Errors.Select(e => e.Description));
await Toast.Error(msg);
}
}
public class RegisterModel
{
[Required]
public string UserName { get; set; } = "";
[Required, EmailAddress]
public string Email { get; set; } = "";
[Required]
public string Password { get; set; } = "";
public string ConfirmPwd { get; set; } = "";
}}
四、登录页面 Login.razor(BootstrapBlazor)
路径 Pages/Account/Login.razor
@page "/account/login"@inject SignInManager
@inject NavigationManager Nav
@inject ToastService Toast
<Body>
<EditForm Model="@loginModel" OnValidSubmit="@LoginSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<FormInput @bind-Value="loginModel.UserName" Label="用户名" />
<FormInput @bind-Value="loginModel.Password" Label="密码" InputType="InputType.Password" />
<Checkbox @bind-Value="loginModel.RememberMe" Label="记住登录" />
<Button Type="ButtonType.Submit" Color="Color.Primary" Class="mt-3">登录</Button>
<a href="/account/register" class="ms-3">没有账号去注册</a>
</EditForm>
</Body>@code {
private LoginModel loginModel = new();
private async Task LoginSubmit()
{
var result = await SignInManager.PasswordSignInAsync(
loginModel.UserName,
loginModel.Password,
loginModel.RememberMe,
lockoutOnFailure: false);
if (result.Succeeded)
{
await Toast.Success("登录成功");
Nav.NavigateTo("/admin/product"); // 跳后台页面
}
else
{
await Toast.Error("用户名或密码错误");
}
}
public class LoginModel
{
[Required]
public string UserName { get; set; } = "";
[Required]
public string Password { get; set; } = "";
public bool RememberMe { get; set; }
}}
五、全局授权拦截:未登录跳转登录
App.razor 包裹路由,添加授权
<Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@MainLayout"> <NotAuthorized> @* 未登录自动跳转到登录页 *@ <RedirectToLogin /> </NotAuthorized> </AuthorizeRouteView> </Found> <NotFound> <PageNotFound /> </NotFound>新建 RedirectToLogin.razor
@inject NavigationManager Nav
@inject AuthenticationStateProvider Auth
@code {
protected override void OnInitialized()
{
Nav.NavigateTo("/account/login?returnUrl=" + Uri.EscapeDataString(Nav.ToBaseRelativePath(Nav.Uri)));
}}
后台页面添加 [Authorize] 限制访问
@page "/admin/product"
@attribute [Authorize] // 必须登录才能访问
@inject AuthenticationStateProvider AuthProvider
@inject AppDbContext Db
@inject ToastService Toast
六、后台页面:新增数据自动保存当前登录用户名
后台商品管理页面 /Admin/Product.razor,新增时自动赋值 CreateUserName
@page "/admin/product"@attribute [Authorize]
@inject AuthenticationStateProvider AuthProvider
@inject AppDbContext Db
@inject ToastService Toast
<Body>
<Button Color="Color.Primary" OnClick="@OpenAddDialog">新增商品</Button>
<Table TItems="@productList" Class="mt-3">
<TableColumn Field="p=>p.Id" Title="ID" />
<TableColumn Field="p=>p.Name" Title="商品名称" />
<TableColumn Field="p=>p.Price" Title="价格" />
<TableColumn Field="p=>p.CreateUserName" Title="创建人" />
<TableColumn Field="p=>p.CreateTime" Title="创建时间" />
</Table>
</Body>@ 新增弹窗 @
<FormInput @bind-Value="currentProduct.Name" Label="商品名称" />
<FormInput @bind-Value="currentProduct.Price" Label="价格" InputType="InputType.Number" />@code {
private Dialog addDialog = new();
private List<Product> productList = new();
private Product currentProduct = new();
private string loginUserName = "";
protected override async Task OnInitializedAsync()
{
// 获取当前登录用户名
loginUserName = await AuthHelper.GetUserNameAsync(AuthProvider);
await LoadData();
}
// 加载列表
private async Task LoadData()
{
productList = await Db.Products.ToListAsync();
}
// 打开新增弹窗
private void OpenAddDialog()
{
currentProduct = new();
addDialog.Show();
}
// 保存数据,自动写入当前登录用户名
private async Task SaveProduct()
{
// 核心:自动绑定登录账号
currentProduct.CreateUserName = loginUserName;
currentProduct.CreateTime = DateTime.Now;
Db.Products.Add(currentProduct);
await Db.SaveChangesAsync();
await Toast.Success("保存成功");
addDialog.Close();
await LoadData();
}}
七、退出登录功能(布局顶部导航栏)
在 MainLayout.razor 顶部导航增加退出按钮
@inject SignInManager<AppUser> SignInManager@inject NavigationManager Nav
@inject AuthenticationStateProvider AuthProvider
@code {
private async Task Logout()
{
await SignInManager.SignOutAsync();
Nav.NavigateTo("/account/login");
}}
完整功能总结
注册:Identity 创建用户,密码校验,注册自动登录
登录:账号密码校验,Cookie 持久登录
授权拦截:未登录自动跳转登录页,后台页面加 [Authorize]
获取登录人:全局 AuthHelper 读取当前用户名
保存数据:新增业务数据时自动赋值 CreateUserName 记录操作人
界面全部使用 BootstrapBlazor 内置表单、弹窗、表格、提示组件
退出登录清除身份 Cookie,跳转登录
评论 (0)