Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article explique comment sécuriser une Blazor Web Appauthentification Windows à l’aide d’un exemple d’application. Pour plus d’informations, consultez Configurer l’authentification Windows dans ASP.NET Core.
Spécification de l’application pour l’Blazor Web App :
- Adopte le mode de rendu serveur interactif avec une interactivité globale.
- Établit une stratégie d’autorisation pour un identificateur de sécurité Windows pour accéder à une page sécurisée.
Exemple d’application
Accédez à l’exemple via le dossier de la dernière version dans le répertoire des échantillons Blazor avec le lien suivant. L’exemple se trouve dans le dossier BlazorWebAppWinAuthServer pour .NET 9 ou version ultérieure.
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Paramétrage
L’exemple d’application ne nécessite pas de configuration pour s’exécuter localement.
Lorsqu’elle est déployée sur un hôte, par exemple IIS, l’application doit adopter l’emprunt d’identité pour s’exécuter sous le compte de l’utilisateur. Pour plus d’informations, consultez Configurer l’authentification Windows dans ASP.NET Core.
Exemple de code d’application
Inspectez le Program fichier dans l’exemple d’application pour les appels d’API suivants.
AddAuthentication est appelé à l’aide du schéma d’authentification NegotiateDefaults.AuthenticationScheme . AddNegotiate configure l’authentification AuthenticationBuilder Negotiate (également appelée authentification Windows, Kerberos ou NTLM) et le gestionnaire d’authentification prend en charge Kerberos sur les serveurs Windows et Linux :
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
AddAuthorization ajoute des services de politique d’autorisation. AuthorizationOptions.FallbackPolicy définit la stratégie d’autorisation de secours, qui est définie sur la stratégie par défaut (AuthorizationOptions.DefaultPolicy). La stratégie par défaut nécessite qu’un utilisateur authentifié accède à l’application :
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
});
AddCascadingAuthenticationState ajoute l’état d’authentification en cascade à la collection de services. Cela équivaut à placer un CascadingAuthenticationState composant à la racine de la hiérarchie des composants de l’application :
builder.Services.AddCascadingAuthenticationState();
Une stratégie d’autorisation est ajoutée pour un IDENTIFICATEUR de sécurité Windows (SID). Le S-1-5-113 SID connu dans l’exemple suivant indique que l’utilisateur est un compte local, qui limite la connexion réseau aux comptes locaux au lieu de « administrateur » ou de comptes équivalents :
builder.Services.AddAuthorizationBuilder()
.AddPolicy("LocalAccount", policy =>
policy.RequireClaim(
"http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",
"S-1-5-113"));
La stratégie d’autorisation est appliquée par le composant LocalAccount.
Components/Pages/LocalAccount.razor :
@page "/local-account"
@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>
Le UserClaims composant répertorie les revendications et les rôles de l’utilisateur, y compris les identificateurs de sécurité Windows (SID) de l’utilisateur avec des traductions 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";
}
}
}