mcpField
A
asp-net-core-identity-patterns

asp-net-core-identity-patterns

github.com/wshaddix安全8689 次安装35 周前更新
代码仓库

关于 asp-net-core-identity-patterns

面向 ASP.NET Core Identity 的安全实践指南,尤其适用于 Razor Pages。内容涵盖 .NET 8 及更高版本的配置、加固、测试与可观测性。

主要功能

  1. 01Identity 设置与配置
  2. 02Razor Pages 身份验证模式
  3. 03基于策略的授权指导
  4. 04Cookie 与登录安全加固
  5. 05身份验证测试与监控

适用场景

  1. 01构建注册和登录流程
  2. 02添加角色、声明或双重身份验证
  3. 03生产部署前加固 ASP.NET Core Identity

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill asp-net-core-identity-patterns

安装后在 Claude Code 中输入/asp-net-core-identity-patterns确认已加载。

详细介绍

你是一名资深 .NET 安全与身份架构师。当任务涉及 ASP.NET Core(尤其是 Razor Pages)中的用户身份验证、注册、登录、角色、声明、双重身份验证、外部登录或授权时,请严格遵循这些模式。优先考虑符合 OWASP 要求、最小权限、可观测性和最小攻击面。目标版本为 .NET 8+,并启用可空引用类型。

原因

ASP.NET Core Identity 提供了强大的成员管理功能(用户、角色、声明、令牌),但其默认设置面向开发者便利,而非生产环境安全加固。配置错误可能导致密码强度不足、会话劫持、用户枚举攻击或合规性问题(GDPR、SOC2)。这些模式可确保安全的默认设置、正确的流程以及可测试的集成。

核心设置(Program.cs / Startup)

  • 使用 AddDefaultIdentity<IdentityUser>(),或使用 AddIdentity<IdentityUser, IdentityRole>() 以支持角色。
  • 链接调用 AddEntityFrameworkStores<ApplicationDbContext>()。
  • 始终尽早配置选项:
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
{
    // Password policy - enforce strong defaults
    options.Password.RequiredLength = 12;
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireUppercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequiredUniqueChars = 6;

    // Lockout - prevent brute force
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // Sign-in requirements
    options.SignIn.RequireConfirmedAccount = true;          // Email confirmation mandatory
    options.SignIn.RequireConfirmedEmail = true;
    options.SignIn.RequireConfirmedPhoneNumber = false;     // Optional 2FA/SMS

    // User settings
    options.User.RequireUniqueEmail = true;
    options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();  // For password reset, email confirmation, 2FA
  • 在 UseRouting() 之后添加身份验证和授权中间件:
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
  • 全局启用 HTTPS 强制执行:
app.UseHsts();
app.UseHttpsRedirection();

Razor Pages 集成

  • 按需选择性地搭建 Identity UI:
dotnet aspnet-codegenerator identity -dc ApplicationDbContext \
  --files "Account.Register;Account.Login;Account.Logout;Account.ForgotPassword;Account.ConfirmEmail;Account.Manage.Index;Account.Manage.ChangePassword;Account.Manage.TwoFactorAuthentication"
  • 在 PageModel 中注入服务:
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<RegisterModel> _logger;

public RegisterModel(
    UserManager<IdentityUser> userManager,
    SignInManager<IdentityUser> signInManager,
    ILogger<RegisterModel> logger)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _logger = logger;
}
  • 始终在表单中验证防伪令牌:使用 @Html.AntiForgeryToken(),并在 POST 处理程序上添加 [ValidateAntiForgeryToken]。
  • 在受保护的 PageModel 上使用 [Authorize]:
[Authorize(Policy = "RequireAdminRole")]
public class AdminModel : PageModel { ... }

授权模式

  • 在可能的情况下,优先使用基于策略的授权,而非基于角色的授权:
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdminRole", policy =>
        policy.RequireRole("Admin"));

    options.AddPolicy("CanEditContent", policy =>
        policy.RequireClaim("Permission", "EditContent")
              .RequireAuthenticatedUser());
});
  • 通过 [Authorize(Policy = "CanEditContent")] 或在端点上使用 RequireAuthorization() 应用策略。

安全加固

  • Cookie 配置:
builder.Services.ConfigureApplicationCookie(options =>
{
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;  // HTTPS only
    options.Cookie.SameSite = SameSiteMode.Strict;            // Mitigate CSRF
    options.ExpireTimeSpan = TimeSpan.FromDays(14);
    options.SlidingExpiration = true;
    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
});
  • 对敏感应用默认启用双重身份验证:通过 TwoFactorAuthentication 页面引导用户完成设置。
  • 使用电子邮件确认令牌;在生产环境中,绝不让未经确认的用户自动登录。
  • 对登录和注册端点进行速率限制(使用 AspNetCoreRateLimit 或中间件)。
  • 通过 Microsoft.AspNetCore.Identity meters(.NET 10+ 新增)记录 Identity 事件,以检测异常。

外部提供程序

  • 添加 Google、Microsoft 等提供程序:
builder.Services.AddAuthentication()
    .AddGoogle(options =>
    {
        options.ClientId = builder.Configuration["Authentication:Google:ClientId"];
        options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
    });
  • 在登录页面中使用 SignInManager.GetExternalAuthenticationSchemesAsync() 动态显示方案。

自定义用户 / 声明

  • 谨慎扩展 IdentityUser(添加 FirstName、LastName 等属性):
public class ApplicationUser : IdentityUser
{
    public string FullName { get; set; } = string.Empty;
}
  • 登录后通过 SignInManager 或自定义声明工厂添加声明。

测试与可观测性

  • 使用 UserManager / SignInManager 模拟对象(Moq)进行单元测试。
  • 使用 WebApplicationFactory 对身份验证流程进行集成测试。
  • 使用 OpenTelemetry / App Insights 监控登录耗时、失败次数和锁定情况。

示例:安全的注册处理程序代码片段

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid) return Page();

    var user = CreateUser();  // Factory method
    await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
    await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);

    var result = await _userManager.CreateAsync(user, Input.Password);
    if (result.Succeeded)
    {
        _logger.LogInformation("User created a new account with password.");

        var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
        // Send email with confirmation link...

        if (_userManager.Options.SignIn.RequireConfirmedAccount)
            return RedirectToPage("RegisterConfirmation", new { email = Input.Email });

        await _signInManager.SignInAsync(user, isPersistent: false);
        return LocalRedirect(returnUrl);
    }

    foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error.Description);
    return Page();
}

反模式

  • 在生产环境中禁用电子邮件确认 → 会导致虚假 / 垃圾账号。
  • 密码策略过弱 → 至少使用 12 个字符并包含复杂度要求。
  • 在代码中存储密钥 → 使用 User Secrets / Azure Key Vault。
  • 到处使用 [Authorize(Roles = "Admin")] → 优先使用声明 / 策略。
  • 忽略锁定机制 → 会导致暴力破解攻击。
  • 在生产环境中发布完整的 Identity UI 资源 → 仅搭建所需页面;排除静态文件。

参考资料

当任务涉及身份验证 / Identity 时,应用此技能。请与 razor-pages-patterns、web-security-hardening 或 dependency-injection-patterns 交叉参考。

评论

支持 Markdown