Microsoft Entra (ME-ID) 组、管理员角色和应用角色(.NET 5 到 .NET 7)
注意
此版本不是本文的最新版本。 有关当前 ASP.NET Core 版本,请参阅具有 Microsoft Entra ID 组和角色的最新版本的 ASP.NET CoreBlazor WebAssembly。
本文介绍如何配置 Blazor WebAssembly 以使用 Microsoft Entra ID 组和角色。
Microsoft Entra (ME-ID) 提供了多种授权方法,这些方法可与 ASP.NET Core Identity 结合使用:
- 组
- 安全性
- Microsoft 365
- 分布
- 角色
- ME-ID 管理员角色
- 应用角色
本文中的指南适用于以下文章中所述的 Blazor WebAssembly ME-ID 部署方案:
本文的指南提供了有关客户端和服务器应用的说明:
- 客户端:独立 Blazor WebAssembly 应用或托管的 Blazor解决方案的 Client 应用。
- 服务器:ASP.NET Core 服务器 API/Web API 应用或托管 Blazor 解决方案的 Server 应用。 对于独立 Blazor WebAssembly 应用,可以忽略整个文章中的 SERVER 指南。
本文中的示例会利用新的 .NET/C# 功能。 使用 .NET 7 或更早版本中的示例时,需要稍作修改。 但是,与 ME-ID 和 Microsoft Graph 交互有关的文本和代码示例对所有版本的 ASP.NET Core 都是相同的。
先决条件
本文中的指南根据将图形 API 与 ASP.NET Core Blazor WebAssembly 配合使用中的 Graph SDK 指南实现 Microsoft Graph API。 按照 Graph SDK 实现指南配置应用并对其进行测试,以确认应用可以获取测试用户帐户的图形 API 数据。 此外,请参阅图形 API 文章的安全文章交叉链接,以查看 Microsoft Graph 安全概念。
在本地使用 Graph SDK 进行测试时,建议为每个测试使用一个新的专用/隐身浏览器会话,防止 Cookie 干扰测试的情况继续存在。 有关详细信息,请参阅使用 Microsoft Entra ID 保护 ASP.NET Core Blazor WebAssembly 独立应用。
作用域
若要允许 Microsoft Graph API 调用用户配置文件、角色分配和组成员身份数据:
- 在 Azure 门户中,CLIENT 应用配置了委托
User.Read
范围 (https://graph.microsoft.com/User.Read
),因为读取用户数据的访问权限由授予(委托)给单个用户的范围决定。 - 在 Azure 门户中,SERVER 应用配置了应用程序
GroupMember.Read.All
范围 (https://graph.microsoft.com/GroupMember.Read.All
),因为访问权限是为了让应用获取有关组成员身份的信息,而不是基于单个用户授权来访问有关组成员的数据。
除前面所列文章(《Microsoft 帐户的独立产品》、《ME-ID 的独立产品》和《使用 ME-ID 托管》)介绍的 ME-ID 部署方案中所需的作用域外,还需要上述作用域。
有关详细信息,请参阅 Microsoft identity 平台中的权限和同意概述以及 Microsoft Graph 权限概述。
权限和作用域是同一个意思,在安全文档和 Azure 门户中可以互换使用。 除非文本引用 Azure 门户,否则本文在引用 Graph 权限时使用作用域/作用域。
范围不区分大小写,因此 User.Read
与 user.read
相同。 请随意使用任一格式,但我们建议在应用程序代码之间保持一致选择。
组成员身份声明属性
在 Azure 门户的 CLIENT 和 SERVER 应用的应用清单中,将 groupMembershipClaims
属性设置为 DirectoryRole
。 值为 DirectoryRole
会导致 ME-ID 在已知 ID 声明 (wids
) 中发送已登录用户的所有角色:
- 打开应用的 Azure 门户注册。
- 在边栏中选择“管理”>“清单”。
- 查找
groupMembershipClaims
属性。 - 将值设置为
DirectoryRole
("groupMembershipClaims": "DirectoryRole"
)。 - 如果进行了更改,请选择“保存”按钮。
在 Azure 门户的 CLIENT 和 SERVER 应用的应用清单中,将 groupMembershipClaims
属性设置为 All
。 值为 All
会导致 ME-ID 在已知 ID 声明 (wids
) 中发送已登录用户的所有安全组、通讯组和角色:
- 打开应用的 Azure 门户注册。
- 在边栏中选择“管理”>“清单”。
- 查找
groupMembershipClaims
属性。 - 将值设置为
All
("groupMembershipClaims": "All"
)。 - 如果进行了更改,请选择“保存”按钮。
自定义用户帐户
将用户分配到 Azure 门户中的 ME-ID 安全组和 ME-ID 管理员角色。
本文中的示例:
- 假设将用户分配到 Azure 门户 ME-ID 租户中的 ME-ID 计费管理员角色,以授权访问服务器 API 数据。
- 使用授权策略在 CLIENT 和 SERVER 应用中控制访问。
在 CLIENT 应用中,将 RemoteUserAccount 扩展为包含以下属性:
Roles
:ME-ID 应用角色数组(包含在应用角色部分)Wids
:已知 ID 声明 (wids
) 中的 ME-ID 管理员角色Oid
:不可变对象标识符声明 (oid
)(唯一标识租户内和跨租户的用户)
CustomUserAccount.cs
:
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
namespace BlazorSample;
public class CustomUserAccount : RemoteUserAccount
{
[JsonPropertyName("roles")]
public List<string>? Roles { get; set; }
[JsonPropertyName("wids")]
public List<string>? Wids { get; set; }
[JsonPropertyName("oid")]
public string? Oid { get; set; }
}
向 Microsoft.Graph
的 CLIENT 应用添加包引用。
注意
有关将包添加到 .NET 应用的指南,请参阅包使用工作流(NuGet 文档)中“安装和管理包”下的文章。 在 NuGet.org 中确认正确的包版本。
在将图形 API 与 ASP.NET Core Blazor WebAssembly 一起使用一文的 Graph SDK 部分中,添加 Graph SDK 实用工具类和配置。 指定 User.Read
访问令牌的作用域,如文章的示例 wwwroot/appsettings.json
文件中所示。
将以下自定义用户帐户工厂添加到 CLIENT 应用。 自定义用户工厂用于建立以下内容:
- 应用角色声明 (
appRole
)(包含在应用角色部分)。 - ME-ID 管理员角色声明 (
directoryRole
)。 - 用户移动电话号码的示例用户配置文件数据声明 (
mobilePhone
) 和办公地点 (officeLocation
)。 - ME-ID 组声明 (
directoryGroup
)。 - ILogger (
logger
),便于你要记录信息或错误时使用。
CustomAccountFactory.cs
:
using System.Security.Claims;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using Microsoft.Graph;
using Microsoft.Kiota.Abstractions.Authentication;
namespace BlazorSample;
public class CustomAccountFactory()
: AccountClaimsPrincipalFactory<CustomUserAccount>
{
private readonly ILogger<CustomAccountFactory> logger;
private readonly IServiceProvider serviceProvider;
private readonly string? baseUrl =
string.Join("/",
config.GetSection("MicrosoftGraph")["BaseUrl"] ??
"https://graph.microsoft.com",
config.GetSection("MicrosoftGraph")["Version"] ??
"v1.0");
public CustomAccountFactory(IAccessTokenProviderAccessor accessor,
IServiceProvider serviceProvider,
ILogger<CustomAccountFactory> logger)
: base(accessor)
{
this.serviceProvider = serviceProvider;
this.logger = logger;
}
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
CustomUserAccount account,
RemoteAuthenticationUserOptions options)
{
var initialUser = await base.CreateUserAsync(account, options);
if (initialUser.Identity is not null &&
initialUser.Identity.IsAuthenticated)
{
var userIdentity = initialUser.Identity as ClaimsIdentity;
if (userIdentity is not null && !string.IsNullOrEmpty(baseUrl))
{
account?.Roles?.ForEach((role) =>
{
userIdentity.AddClaim(new Claim("appRole", role));
});
account?.Wids?.ForEach((wid) =>
{
userIdentity.AddClaim(new Claim("directoryRole", wid));
});
try
{
var client = new GraphServiceClient(
new HttpClient(),
serviceProvider
.GetRequiredService<IAuthenticationProvider>(),
baseUrl);
var user = await client.Me.GetAsync();
if (user is not null)
{
userIdentity.AddClaim(new Claim("mobilephone",
user.MobilePhone ?? "(000) 000-0000"));
userIdentity.AddClaim(new Claim("officelocation",
user.OfficeLocation ?? "Not set"));
}
var requestMemberOf = client.Users[account?.Oid].MemberOf;
var graphGroups = await requestMemberOf.GraphGroup.GetAsync();
if (graphGroups?.Value is not null)
{
foreach (var entry in graphGroups.Value)
{
if (entry.Id is not null)
{
userIdentity.AddClaim(
new Claim("directoryGroup", entry.Id));
}
}
}
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
}
return initialUser;
}
}
using System.Security.Claims;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using Microsoft.Graph;
namespace BlazorSample;
public class CustomAccountFactory()
: AccountClaimsPrincipalFactory<CustomUserAccount>(accessor)
{
private readonly ILogger<CustomAccountFactory> logger;
private readonly IServiceProvider serviceProvider;
public CustomAccountFactory(IAccessTokenProviderAccessor accessor,
IServiceProvider serviceProvider,
ILogger<CustomAccountFactory> logger)
: base(accessor)
{
this.serviceProvider = serviceProvider;
this.logger = logger;
}
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
CustomUserAccount account,
RemoteAuthenticationUserOptions options)
{
var initialUser = await base.CreateUserAsync(account, options);
if (initialUser.Identity is not null &&
initialUser.Identity.IsAuthenticated)
{
var userIdentity = initialUser.Identity as ClaimsIdentity;
if (userIdentity is not null)
{
account?.Roles?.ForEach((role) =>
{
userIdentity.AddClaim(new Claim("appRole", role));
});
account?.Wids?.ForEach((wid) =>
{
userIdentity.AddClaim(new Claim("directoryRole", wid));
});
try
{
var client = ActivatorUtilities
.CreateInstance<GraphServiceClient>(serviceProvider);
var request = client.Me.Request();
var user = await request.GetAsync();
if (user is not null)
{
userIdentity.AddClaim(new Claim("mobilephone",
user.MobilePhone ?? "(000) 000-0000"));
userIdentity.AddClaim(new Claim("officelocation",
user.OfficeLocation ?? "Not set"));
}
var requestMemberOf = client.Users[account?.Oid].MemberOf;
var memberships = await requestMemberOf.Request().GetAsync();
if (memberships is not null)
{
foreach (var entry in memberships)
{
if (entry.ODataType == "#microsoft.graph.group")
{
userIdentity.AddClaim(
new Claim("directoryGroup", entry.Id));
}
}
}
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
}
return initialUser;
}
}
上面的代码不包含可传递的成员身份。 如果应用需要直接且可传递的组成员身份声明,请将 MemberOf
属性 (IUserMemberOfCollectionWithReferencesRequestBuilder
) 替换为 TransitiveMemberOf
(IUserTransitiveMemberOfCollectionWithReferencesRequestBuilder
)。
上述代码将忽略作为 ME-ID 管理员角色(#microsoft.graph.directoryRole
类型)的组成员身份声明 (groups
),因为 ME-ID 返回的 GUID 值为管理员角色实体 ID,而不是角色模板 ID。 实体 ID 在各租户之间不稳定,因此不应用于为应用中的用户创建授权策略。 始终对 wids
声明提供的 ME-ID 管理员角色使用模板 ID。
租户的非来宾帐户存在值为 b79fbf4d-3ef9-4689-8143-76b194e85509
的 wids
声明(以及 directoryRole
声明)。 它不引用 ME-ID 管理员角色模板 ID。
在 CLIENT 应用中,将 MSAL 身份验证配置为使用自定义用户帐户工厂。
确认 Program
文件使用 Microsoft.AspNetCore.Components.WebAssembly.Authentication 命名空间:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
更新对以下内容的 AddMsalAuthentication 调用。 请注意,Blazor 框架的 RemoteUserAccount 将替换为 MSAL 身份验证和帐户声明主体工厂的应用的 CustomUserAccount
:
builder.Services.AddMsalAuthentication<RemoteAuthenticationState,
CustomUserAccount>(options =>
{
builder.Configuration.Bind("AzureAd",
options.ProviderOptions.Authentication);
})
.AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount,
CustomAccountFactory>();
确认是否存在将图形 API 与 ASP.NET Core Blazor WebAssembly 一起使用一文中所述的 Graph SDK 代码,并根据 Graph SDK 指南确认 wwwroot/appsettings.json
配置是否正确:
var baseUrl =
string.Join("/",
builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"] ??
"https://graph.microsoft.com",
builder.Configuration.GetSection("MicrosoftGraph")["Version"] ??
"v1.0");
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
.Get<List<string>>() ?? [ "user.read" ];
builder.Services.AddGraphClient(baseUrl, scopes);
wwwroot/appsettings.json
:
{
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com",
"Version": "v1.0",
"Scopes": [
"user.read"
]
}
}
授权配置
在客户端应用中,为每个应用角色、ME-ID 管理员角色或 Program
文件中的安全组创建策略。 以下示例为 ME-ID 内置计费管理员角色创建策略:
builder.Services.AddAuthorizationCore(options =>
{
options.AddPolicy("BillingAdministrator", policy =>
policy.RequireClaim("directoryRole",
"b0f54661-2d74-4c50-afa3-1ec803f12efe"));
});
有关 ME-ID 管理员角色 ID 的完整列表,请参阅 Entra 文档中的角色模板 ID。 有关授权策略详细信息,请参阅 ASP.NET Core 中基于策略的授权。
在以下示例中,CLIENT 应用使用前面的策略来授权用户。
AuthorizeView
组件适用于以下策略:
<AuthorizeView Policy="BillingAdministrator">
<Authorized>
<p>
The user is in the 'Billing Administrator' ME-ID Administrator Role
and can see this content.
</p>
</Authorized>
<NotAuthorized>
<p>
The user is NOT in the 'Billing Administrator' role and sees this
content.
</p>
</NotAuthorized>
</AuthorizeView>
对整个组件的访问可以基于使用 [Authorize]
属性指令 (AuthorizeAttribute) 的策略:
@page "/"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "BillingAdministrator")]
如果用户未获得授权,则会将他们重定向到 ME-ID 登录页。
策略检查也可以在具有过程逻辑的代码中执行。
CheckPolicy.razor
:
@page "/checkpolicy"
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
<h1>Check Policy</h1>
<p>This component checks a policy in code.</p>
<button @onclick="CheckPolicy">Check 'BillingAdministrator' policy</button>
<p>Policy Message: @policyMessage</p>
@code {
private string policyMessage = "Check hasn't been made yet.";
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
private async Task CheckPolicy()
{
var user = (await authenticationStateTask).User;
if ((await AuthorizationService.AuthorizeAsync(user,
"BillingAdministrator")).Succeeded)
{
policyMessage = "Yes! The 'BillingAdministrator' policy is met.";
}
else
{
policyMessage = "No! 'BillingAdministrator' policy is NOT met.";
}
}
}
通过使用上述方法,还可以为应用角色(其中,用于策略的 GUID 是在 Azure 门户中应用清单的 appRoles
元素中设置的)以及安全组(其中,用于策略的 GUID 与 Azure 门户的“组”窗格中的组对象 ID 匹配)创建基于策略的访问。
授权服务器 API/web API 访问
当访问令牌包含 groups
、wids
和 role
声明时,SERVER API 应用可以通过授权策略授权用户访问安全组、ME-ID 管理员角色和应用角色的安全 API 终结点。 下面的示例使用 wids
(已知 ID/角色模板 ID)声明,在 Program
文件中为 ME-ID 计费管理员角色创建策略:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("BillingAdministrator", policy =>
policy.RequireClaim("wids", "b0f54661-2d74-4c50-afa3-1ec803f12efe"));
});
有关 ME-ID 管理员角色 ID 的完整列表,请参阅 Azure 文档中的角色模板 ID。 有关授权策略详细信息,请参阅 ASP.NET Core 中基于策略的授权。
对 SERVER 应用中的控制器的访问可以基于将 [Authorize]
属性 与策略名称(API 文档:AuthorizeAttribute)结合使用。
下面的示例使用名为 BillingAdministrator
的策略,对 BillingDataController
中计费数据的访问限制为 Azure 计费管理员:
using Microsoft.AspNetCore.Authorization;
[Authorize(Policy = "BillingAdministrator")]
[ApiController]
[Route("[controller]")]
public class BillingDataController : ControllerBase
{
...
}
有关详细信息,请参阅 ASP.NET Core 中基于策略的授权。
应用角色
要在 Azure 门户中配置应用以提供应用角色成员资格声明,请参阅 Entra 文档中的在应用程序中添加应用角色并在令牌中接收这些角色。
下面的示例假定 CLIENT 和 SERVER 应用配置了两个角色,并将角色分配给测试用户:
Admin
Developer
注意
当开发托管 Blazor WebAssembly 应用或独立应用的客户端服务器对(独立 Blazor WebAssembly 应用和 ASP.NET Core 服务器 API/Web API 应用)时,客户端和服务器 Azure 门户应用注册的 appRoles
清单属性必须包含相同的已配置角色。 在客户端应用清单中建立角色后,请将它们全部复制到服务器应用清单中。 如果未在客户端和服务器应用注册之间映射清单 appRoles
,则不会为服务器 API/Web API 的经过身份验证的用户建立角色声明,即使其访问令牌在声明中具有正确的实体也是如此。
尽管没有 Microsoft Entra ID Premium 帐户就无法将角色分配给组,但你可以将角色分配给用户,并为具有标准 Azure 帐户的用户接收角色声明。 本部分中的指南不需要 ME-ID Premium 帐户。
使用默认目录时,请按照在应用程序中添加应用角色并在令牌中接收这些角色中的指南来配置并分配角色。 如果不使用默认目录,请在Azure 门户中编辑应用的清单,以在清单文件的 appRoles
条目中手动建立应用的角色。 下面是创建 Admin
和 Developer
角色的示例 appRoles
条目。 本节稍后在组件级别的示例中使用这些示例角色来实现访问限制:
"appRoles": [
{
"allowedMemberTypes": [
"User"
],
"description": "Administrators manage developers.",
"displayName": "Admin",
"id": "{ADMIN GUID}",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "Admin"
},
{
"allowedMemberTypes": [
"User"
],
"description": "Developers write code.",
"displayName": "Developer",
"id": "{DEVELOPER GUID}",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "Developer"
}
],
对于前面的示例中的{ADMIN GUID}
占位符和{DEVELOPER GUID}
占位符,可以使用联机 GUID 生成器生成 GUID(“guid 生成器”的 Google 搜索结果)。
若要将角色分配给用户(或组,如果你有高级层 Azure 帐户),请执行以下操作:
- 导航到 Azure 门户的 ME-ID 区域中的“企业应用程序”。
- 选择应用。 从边栏中选择“管理”>“用户和组”。
- 选中一个或多个用户帐户的复选框。
- 在用户列表上方的菜单中,选择“编辑分配”。
- 对于“选择角色”条目,选择“未选择任何项”。
- 从列表中选择一个角色,并使用“选择”按钮将其选中。
- 使用屏幕底部的“分配”按钮分配角色。
通过为其他每个角色分配重新添加用户,在 Azure 门户中分配多个角色。 使用用户列表顶部的“添加用户/组”按钮重新添加用户。 使用上述步骤向用户分配另一个角色。 可以根据需要多次重复此过程,将其他角色添加到用户(或组)。
自定义用户帐户部分中显示的 CustomAccountFactory
设置为使用 JSON 数组值应对 role
声明。 在 CLIENT 应用中添加并注册 CustomAccountFactory
,如自定义用户帐户部分所示。 无需提供代码来删除原始 role
声明,因为框架会自动删除它。
在客户端应用的 Program
文件中,指定名为“appRole
”的声明作为 ClaimsPrincipal.IsInRole 检查的角色声明:
builder.Services.AddMsalAuthentication(options =>
{
...
options.UserOptions.RoleClaim = "appRole";
});
注意
如果希望使用 directoryRoles
声明(ADD 管理员角色),请将“directoryRoles
”分配给 RemoteAuthenticationUserOptions.RoleClaim。
在服务器应用的 Program
文件中,指定名为“http://schemas.microsoft.com/ws/2008/06/identity/claims/role
”的声明作为 ClaimsPrincipal.IsInRole 检查的角色声明:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAd", options);
options.TokenValidationParameters.RoleClaimType =
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
},
options => { Configuration.Bind("AzureAd", options); });
注意
注册单个身份验证方案时,身份验证方案将自动用作应用的默认方案,无需向 AddAuthentication 或通过 AuthenticationOptions 声明方案。 有关详细信息,请参阅 ASP.NET Core 身份验证概述和 ASP.NET Core 公告 (aspnet/Announcements #490)。
注意
如果希望使用 wids
声明(ADD 管理员角色),请将“wids
”分配给 TokenValidationParameters.RoleClaimType。
完成上述步骤以创建角色并将其分配给用户(或组,如果你有高级层 Azure 帐户),并使用 Graph SDK 实现 CustomAccountFactory
,如本文前面和将图形 API 与 ASP.NET Core Blazor WebAssembly 一起使用中所述,应会看到为登录用户分配的每个分配角色(或分配给他们所属的组的角色)都有一个 appRole
声明。 使用测试用户运行应用,以确认声明是否按预期存在。 在本地使用 Graph SDK 进行测试时,建议为每个测试使用一个新的专用/隐身浏览器会话,防止 Cookie 干扰测试的情况继续存在。 有关详细信息,请参阅使用 Microsoft Entra ID 保护 ASP.NET Core Blazor WebAssembly 独立应用。
组件授权方法此时有效。 CLIENT 应用的组件中的任何授权机制都可以使用 Admin
角色来授权用户:
-
<AuthorizeView Roles="Admin">
[Authorize]
属性指令 (AuthorizeAttribute)@attribute [Authorize(Roles = "Admin")]
-
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var user = authState.User; if (user.IsInRole("Admin")) { ... }
支持多个角色测试:
要求用户为
Admin
或Developer
角色,并具有AuthorizeView
组件:<AuthorizeView Roles="Admin, Developer"> ... </AuthorizeView>
要求用户同时为
Admin
和Developer
角色,并具有AuthorizeView
组件:<AuthorizeView Roles="Admin"> <AuthorizeView Roles="Developer" Context="innerContext"> ... </AuthorizeView> </AuthorizeView>
有关
Context
上 AuthorizeView 内部的详细信息,请参阅 ASP.NET Core Blazor身份验证和授权。要求用户为
Admin
或Developer
角色,并具有[Authorize]
属性:@attribute [Authorize(Roles = "Admin, Developer")]
要求用户同时为
Admin
和Developer
角色,并具有[Authorize]
属性:@attribute [Authorize(Roles = "Admin")] @attribute [Authorize(Roles = "Developer")]
要求用户为
Admin
或Developer
角色,并具有过程代码:@code { private async Task DoSomething() { var authState = await AuthenticationStateProvider .GetAuthenticationStateAsync(); var user = authState.User; if (user.IsInRole("Admin") || user.IsInRole("Developer")) { ... } else { ... } } }
要求用户同时为
Admin
或Developer
角色,并具有过程代码,方法是将 条件 OR (||
) 更改为上述示例中的 条件 AND (&&
):if (user.IsInRole("Admin") && user.IsInRole("Developer"))
SERVER 应用的控制器中的任何授权机制都可以使用 Admin
角色来授权用户:
[Authorize]
属性指令 (AuthorizeAttribute)[Authorize(Roles = "Admin")]
-
if (User.IsInRole("Admin")) { ... }
支持多个角色测试:
要求用户为
Admin
或Developer
角色,并具有[Authorize]
属性:[Authorize(Roles = "Admin, Developer")]
要求用户同时为
Admin
和Developer
角色,并具有[Authorize]
属性:[Authorize(Roles = "Admin")] [Authorize(Roles = "Developer")]
要求用户为
Admin
或Developer
角色,并具有过程代码:static readonly string[] scopeRequiredByApi = new string[] { "API.Access" }; ... [HttpGet] public IEnumerable<ReturnType> Get() { HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); if (User.IsInRole("Admin") || User.IsInRole("Developer")) { ... } else { ... } return ... }
要求用户同时为
Admin
或Developer
角色,并具有过程代码,方法是将 条件 OR (||
) 更改为上述示例中的 条件 AND (&&
):if (User.IsInRole("Admin") && User.IsInRole("Developer"))
由于 .NET 字符串比较是区分大小写的,因此匹配角色名称也区分大小写。 例如,Admin
(大写 A
)不被视为与 admin
(小写 a
)相同的角色。
Pascal 大小写通常用于角色名称(例如 BillingAdministrator
),但使用 Pascal 大小写并非严格要求。 允许不同的包装方案,如骆驼元素、烤肉元素和蛇元素。 在角色名称中使用空格也是不常见的,但允许使用。 例如,billing administrator
在 .NET 应用中是一种不常见的角色名称格式,但有效。