使用 Windows 身份验证保护 ASP.NET 核心Blazor Web App

本文介绍如何使用示例应用保护 Blazor Web App Windows 身份验证 。 有关详细信息,请参阅在 ASP.NET Core 中配置 Windows 身份验证

应用程序规范如下 Blazor Web App:

示例应用

使用以下链接通过示例存储库中的 Blazor 最新版本文件夹访问示例。 此示例位于 BlazorWebAppWinAuthServer .NET 9 或更高版本的文件夹中。

查看或下载示例代码如何下载

配置

示例应用不需要配置在本地运行。

部署到主机(如 IIS)时,应用必须采用模拟才能在用户帐户下运行。 有关详细信息,请参阅在 ASP.NET Core 中配置 Windows 身份验证

示例应用代码

检查示例应用中的Program文件,以查看以下 API 调用。

AddAuthentication 通过 NegotiateDefaults.AuthenticationScheme 身份验证方案被调用。 AddNegotiate 配置 AuthenticationBuilder 使用 Negotiate(也称为 Windows、Kerberos 或 NTLM)身份验证,身份验证处理程序支持 Windows 和 Linux 服务器上的 Kerberos:

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate();

AddAuthorization 添加授权策略服务。 AuthorizationOptions.FallbackPolicy 设置回退授权策略,该策略设置为默认策略(AuthorizationOptions.DefaultPolicy)。 默认策略要求经过身份验证的用户访问应用:

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});

AddCascadingAuthenticationState 将级联身份验证状态添加到服务集合。 这相当于将 CascadingAuthenticationState 组件放置在应用的组件层次结构的根目录中:

builder.Services.AddCascadingAuthenticationState();

Windows 安全标识符(SID)添加了授权策略S-1-5-113以下示例中的已知 SID 指示用户是本地帐户,它将网络登录限制为本地帐户,而不是“管理员”或等效帐户:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("LocalAccount", policy =>
        policy.RequireClaim(
            "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",
            "S-1-5-113"));   

授权策略由 LocalAccountOnly 组件强制执行。

Components/Pages/LocalAccountOnly.razor:

@page "/local-account-only"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize("LocalAccount")]

<h1>Local Account Only</h1>

<p>
    You can only reach this page by satisfying the
    <code>LocalAccount</code> authorization policy.
</p>

UserClaims 组件列出用户的声明和角色,包括用户的 Windows 安全标识符(SID)和 SID 翻译。

Components/Pages/UserClaims.razor:

@page "/user-claims"
@using System.Security.Claims
@using System.Security.Principal
@using Microsoft.AspNetCore.Components.QuickGrid

<PageTitle>User Claims & Roles</PageTitle>

<h1>User Claims & Roles</h1>

<QuickGrid Items="claims" Pagination="pagination">
    <Paginator State="pagination" />
    <PropertyColumn Property="@(p => p.Type)" Sortable="true" />
    <PropertyColumn Property="@(p => p.Value)" Sortable="true" />
    <PropertyColumn Property="@(p => GetClaimAsHumanReadable(p))" Sortable="true" Title="Translation" />
    <PropertyColumn Property="@(p => p.Issuer)" Sortable="true" />
</QuickGrid>

<h1>User Roles</h1>

@if (roles.Any())
{
    <ul>
        @foreach (var role in roles)
        {
            <li>@role</li>
        }
    </ul>
}
else
{
    <p>No roles available.</p>
}

@code {
    private IQueryable<Claim> claims = Enumerable.Empty<Claim>().AsQueryable();
    private IEnumerable<string> roles = Enumerable.Empty<string>();
    PaginationState pagination = new PaginationState { ItemsPerPage = 10 };

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

    protected override async Task OnInitializedAsync()
    {
        if (AuthState == null)
        {
            return;
        }

        var authState = await AuthState;

        claims = authState.User.Claims.AsQueryable();

        roles = authState.User.Claims
            .Where(claim => claim.Type == ClaimTypes.Role)
            .Select(claim => claim.Value);
    }

    private string GetClaimAsHumanReadable(Claim claim)
    {
        if (!OperatingSystem.IsWindows() ||
            claim.Type is not (ClaimTypes.PrimarySid or ClaimTypes.PrimaryGroupSid
                or ClaimTypes.GroupSid))
        {
            // We're either not on Windows or not dealing with a SID Claim that
            // can be translated
            return string.Empty;
        }

        SecurityIdentifier sid = new SecurityIdentifier(claim.Value);

        try
        {
            // Throw an exception if the SID can't be translated
            var account = sid.Translate(typeof(NTAccount));

            return account.ToString();
        }
        catch (IdentityNotMappedException)
        {
            return "Could not be mapped";
        }
    }
}

其他资源