Bootstrap Blazor 完整流程:注册 + 登录 + 身份验证 + 后台存数据带用户名

Bootstrap Blazor 完整流程:注册 + 登录 + 身份验证 + 后台存数据带用户名

芯宇宙技术社
2026-07-28 / 0 评论 / 7 阅读 / 正在检测是否收录...

基于 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();



  1. 自定义用户实体 AppUser.cs

扩展需要的字段(手机号、昵称等),继承 IdentityUser

 

   using Microsoft.AspNetCore.Identity;
    
    public class AppUser : IdentityUser
    {
        // 可自定义扩展字段
        public string NickName { get; set; } = "";
    }
  1. 数据库上下文 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;
    }
  1. 迁移数据库

    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 UserManager
@inject SignInManager 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 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; }
}

}

五、全局授权拦截:未登录跳转登录

  1. App.razor 包裹路由,添加授权


     <Found Context="routeData">
         <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@MainLayout">
             <NotAuthorized>
                 @* 未登录自动跳转到登录页 *@
                 <RedirectToLogin />
             </NotAuthorized>
         </AuthorizeRouteView>
     </Found>
     <NotFound>
         <PageNotFound />
     </NotFound>


  2. 新建 RedirectToLogin.razor

    @inject NavigationManager Nav
    @inject AuthenticationStateProvider Auth

@code {

protected override void OnInitialized()
{
    Nav.NavigateTo("/account/login?returnUrl=" + Uri.EscapeDataString(Nav.ToBaseRelativePath(Nav.Uri)));
}

}

  1. 后台页面添加 [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

评论 (0)

取消