configure-auth

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Configure Auth

配置身份验证

Step 1 — Read AGENTS.md

步骤1 — 阅读AGENTS.md

Read
AGENTS.md
at the workspace root for the project's interactivity mode and scope before making changes.
在进行更改前,请阅读工作区根目录下的
AGENTS.md
文件,了解项目的交互模式和范围。

Step 2 — Register auth services in Program.cs

步骤2 — 在Program.cs中注册认证服务

csharp
// Program.cs (server project)
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthorization();
For ASP.NET Core Identity add the Identity services:
csharp
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies();

builder.Services.AddIdentityCore<ApplicationUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager()
    .AddDefaultTokenProviders();
csharp
// Program.cs (服务器项目)
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthorization();
若使用ASP.NET Core Identity,请添加Identity服务:
csharp
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies();

builder.Services.AddIdentityCore<ApplicationUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager()
    .AddDefaultTokenProviders();

Step 3 — Wire App.razor for auth and render mode

步骤3 — 配置App.razor以支持认证和渲染模式

The
App.razor
component must use
AuthorizeRouteView
and conditionally apply the render mode so that pages excluded from interactive routing render statically.
razor
<!DOCTYPE html>
<html>
<head>
    <HeadOutlet @rendermode="RenderModeForPage" />
</head>
<body>
    <Routes @rendermode="RenderModeForPage" />
    <script src="_framework/blazor.web.js"></script>
</body>
</html>

@code {
    [CascadingParameter]
    public HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage =>
        HttpContext.AcceptsInteractiveRouting()
            ? InteractiveServer   // replace with the app's render mode
            : null;
}
In
Routes.razor
(or wherever the router lives), use
AuthorizeRouteView
:
razor
<Router AppAssembly="typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="routeData"
                            DefaultLayout="typeof(Layout.MainLayout)">
            <NotAuthorized>
                @if (context.User.Identity?.IsAuthenticated != true)
                {
                    <RedirectToLogin />
                }
                else
                {
                    <p>You are not authorized to access this resource.</p>
                }
            </NotAuthorized>
        </AuthorizeRouteView>
        <FocusOnNavigate RouteData="routeData" Selector="h1" />
    </Found>
</Router>
App.razor
组件必须使用
AuthorizeRouteView
,并根据条件应用渲染模式,使排除在交互式路由外的页面以静态方式渲染。
razor
<!DOCTYPE html>
<html>
<head>
    <HeadOutlet @rendermode="RenderModeForPage" />
</head>
<body>
    <Routes @rendermode="RenderModeForPage" />
    <script src="_framework/blazor.web.js"></script>
</body>
</html>

@code {
    [CascadingParameter]
    public HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage =>
        HttpContext.AcceptsInteractiveRouting()
            ? InteractiveServer   // 替换为应用的渲染模式
            : null;
}
Routes.razor
(或路由所在的其他文件)中,使用
AuthorizeRouteView
razor
<Router AppAssembly="typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="routeData"
                            DefaultLayout="typeof(Layout.MainLayout)">
            <NotAuthorized>
                @if (context.User.Identity?.IsAuthenticated != true)
                {
                    <RedirectToLogin />
                }
                else
                {
                    <p>您无权访问此资源。</p>
                }
            </NotAuthorized>
        </AuthorizeRouteView>
        <FocusOnNavigate RouteData="routeData" Selector="h1" />
    </Found>
</Router>

Step 4 — Protect pages and components

步骤4 — 保护页面和组件

[Authorize] attribute on pages

页面上的[Authorize]特性

razor
@page "/admin"
@attribute [Authorize]
With roles or policies:
razor
@attribute [Authorize(Roles = "Admin")]
@attribute [Authorize(Policy = "RequireManager")]
razor
@page "/admin"
@attribute [Authorize]
结合角色或策略:
razor
@attribute [Authorize(Roles = "Admin")]
@attribute [Authorize(Policy = "RequireManager")]

AuthorizeView for conditional UI

使用AuthorizeView实现条件UI

razor
<AuthorizeView>
    <Authorized>Welcome, @context.User.Identity?.Name!</Authorized>
    <NotAuthorized><a href="Account/Login">Log in</a></NotAuthorized>
</AuthorizeView>
Role/policy variants:
razor
<AuthorizeView Roles="Admin,Manager">
    <Authorized>Admin content here</Authorized>
</AuthorizeView>
razor
<AuthorizeView>
    <Authorized>欢迎,@context.User.Identity?.Name</Authorized>
    <NotAuthorized><a href="Account/Login">登录</a></NotAuthorized>
</AuthorizeView>
角色/策略变体:
razor
<AuthorizeView Roles="Admin,Manager">
    <Authorized>管理员内容</Authorized>
</AuthorizeView>

Access auth state in code

在代码中访问认证状态

csharp
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }

protected override async Task OnInitializedAsync()
{
    if (AuthState is not null)
    {
        var state = await AuthState;
        var isAdmin = state.User.IsInRole("Admin");
    }
}
csharp
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }

protected override async Task OnInitializedAsync()
{
    if (AuthState is not null)
    {
        var state = await AuthState;
        var isAdmin = state.User.IsInRole("Admin");
    }
}

Step 5 — Identity pages must stay static SSR

步骤5 — Identity页面必须保持静态SSR

SignInManager
and
UserManager
use
HttpContext
internally and throw in interactive components. Identity pages (login, register, manage) must render as static SSR.
In a globally interactive app, mark every Identity page:
razor
@page "/Account/Login"
@attribute [ExcludeFromInteractiveRouting]
This forces a full-page navigation (exits the interactive circuit) so the page renders through the static SSR pipeline with a real
HttpContext
.
App.razor
must use
AcceptsInteractiveRouting()
(Step 3) to return
null
for these pages — otherwise the framework still tries to render them interactively.
In a per-page app, Identity pages are static by default (no
@rendermode
directive), so
[ExcludeFromInteractiveRouting]
is not needed.
SignInManager
UserManager
内部使用
HttpContext
,在交互式组件中会抛出异常。Identity页面(登录、注册、管理)必须以静态SSR方式渲染。
全局交互式应用中,标记所有Identity页面:
razor
@page "/Account/Login"
@attribute [ExcludeFromInteractiveRouting]
这会强制触发全页面导航(退出交互式回路),使页面通过带有真实
HttpContext
的静态SSR管道渲染。
App.razor
必须使用
AcceptsInteractiveRouting()
(步骤3)为这些页面返回
null
,否则框架仍会尝试以交互式方式渲染它们。
按页面配置的应用中,Identity页面默认是静态的(无
@rendermode
指令),因此不需要
[ExcludeFromInteractiveRouting]

Step 6 — Auth state in WebAssembly / Auto mode

步骤6 — WebAssembly / Auto模式下的认证状态

WebAssembly components run in the browser and have no
HttpContext
. Auth state must be serialized from the server during prerendering and deserialized on the client.
Server
Program.cs
:
csharp
builder.Services.AddAuthenticationStateSerialization();
Client
.Client/Program.cs
:
csharp
builder.Services.AddAuthenticationStateDeserialization();
Without these calls,
Task<AuthenticationState>
resolves to an anonymous user after WebAssembly takes over from prerendering.
AddAuthenticationStateSerialization
accepts options to include role and claim data:
csharp
builder.Services.AddAuthenticationStateSerialization(options =>
    options.SerializeAllClaims = true);
WebAssembly组件在浏览器中运行,没有
HttpContext
。认证状态必须在预渲染期间从服务器序列化,然后在客户端反序列化。
服务器端
Program.cs
csharp
builder.Services.AddAuthenticationStateSerialization();
客户端
.Client/Program.cs
csharp
builder.Services.AddAuthenticationStateDeserialization();
如果没有这些调用,当WebAssembly接管预渲染后,
Task<AuthenticationState>
会解析为匿名用户。
AddAuthenticationStateSerialization
接受选项以包含角色和声明数据:
csharp
builder.Services.AddAuthenticationStateSerialization(options =>
    options.SerializeAllClaims = true);

Render Mode × Auth Matrix

渲染模式 × 认证矩阵

Render modeHttpContext.UserSignInManagerAuth state sourceKey requirement
Static SSRAvailableWorksServer pipelineUse middleware for redirects,
<NotAuthorized>
does NOT render
Server (interactive)NOT availableThrows
CascadingAuthenticationState
Use
[Authorize]
+
AuthorizeView
, not
HttpContext
WebAssemblyNOT availableThrowsSerialized from server
AddAuthenticationStateSerialization
/
Deserialization
AutoNOT available after WASMThrowsSerialized from serverSame as WebAssembly; register in both Program.cs files
渲染模式HttpContext.UserSignInManager认证状态来源关键要求
静态SSR可用正常工作服务器管道使用中间件进行重定向,
<NotAuthorized>
不会渲染
Server(交互式)不可用抛出异常
CascadingAuthenticationState
使用
[Authorize]
+
AuthorizeView
,不要使用
HttpContext
WebAssembly不可用抛出异常从服务器序列化而来使用
AddAuthenticationStateSerialization
/
Deserialization
AutoWASM接管后不可用抛出异常从服务器序列化而来与WebAssembly相同;在两个Program.cs文件中注册

Common Mistakes

常见错误

MistakeSymptomFix
Using
HttpContext.User
in interactive component
Null or stale claimsUse
[CascadingParameter] Task<AuthenticationState>
SignInManager
in interactive component
InvalidOperationException
Move to static SSR page with
[ExcludeFromInteractiveRouting]
Missing
AddAuthenticationStateSerialization
Anonymous user after WASM loadsAdd to server Program.cs; add
Deserialization
to client Program.cs
<NotAuthorized>
in static SSR layout
Content never shownStatic SSR uses middleware pipeline; redirect via
LoginPath
or
RedirectToLogin
component
Global interactivity without
AcceptsInteractiveRouting
Identity pages crashAdd
AcceptsInteractiveRouting()
check in App.razor (Step 3)
Missing
AddCascadingAuthenticationState()
Task<AuthenticationState>
is null
Register in Program.cs (Step 2)
错误操作症状修复方法
在交互式组件中使用
HttpContext.User
声明为null或过期使用
[CascadingParameter] Task<AuthenticationState>
在交互式组件中使用
SignInManager
InvalidOperationException
异常
迁移到带有
[ExcludeFromInteractiveRouting]
的静态SSR页面
缺少
AddAuthenticationStateSerialization
WASM加载后变为匿名用户在服务器端Program.cs中添加该服务;在客户端Program.cs中添加
Deserialization
服务
在静态SSR布局中使用
<NotAuthorized>
内容从未显示静态SSR使用中间件管道;通过
LoginPath
RedirectToLogin
组件进行重定向
全局交互式应用未使用
AcceptsInteractiveRouting
Identity页面崩溃在App.razor中添加
AcceptsInteractiveRouting()
检查(步骤3)
缺少
AddCascadingAuthenticationState()
Task<AuthenticationState>
为null
在Program.cs中注册该服务(步骤2)