Identity Server 4 - 如何在实际用例中应用 ApiScope?

Identity Server 4 - How can I apply an ApiScope in a real world use case?

我是 Identity Server 4 的新手。ApiScope 概念不清楚,能否请您更详细地解释一下?以及我们如何实际应用它。

示例:Web API 将有以下模块,我想限制对模块的访问,我可以基于它吗?如果可以,我们如何在系统中配置它

Scopes =
    {
         new Scope()
         {
             Name = "accountmanagement",
             DisplayName = "Account management api",
         },
         new Scope()
         {
             Name = "stockmanagement",
             DisplayName = "Account management api",
         }
    }

谢谢,

范围是一个抽象概念,您可以使用您认为合适的方式来细分(或不细分)您的 API 资源。例如,您可能有:

  • 一个范围涵盖多个物理上不同的 APIs ("OurEnterpriseScope")
  • 每个物理范围一个 API ("OurDataAccessApiScope", "OurFinanceApiScope")
  • 每个物理 API 的多个范围,无论您认为合适的粒度。可能有两个:一个用于读取,一个用于写入。也许一个给普通用户,一个给管理员用户。也许每个端点都有一个范围(但不要...)

在 IdentityServer 中,您可以使用 Client 对象上的 AllowedScopes 指定您的客户端可以访问的范围。因此,您可能有一个只能使用 'MyApiUser' 范围的客户端和一个可以同时使用 'MyApiUser' 范围和 'MyApiAdmin' 范围的不同客户端。

作用域不是user的功能,只是client用户正在使用的功能。

如何拆分资源完全取决于您。

在您的 API 中,您需要在 UseIdentityServerAuthentication 中定义 AllowedScopes,以便您的 API 知道它将在访问令牌中接受哪些范围。如果你有一个接受多个范围的 API 并且你想根据访问令牌的范围来控制对端点的访问(因为你的 API 支持多个客户端,每个客户端都有不同的范围)那么你可以根据 Claims 定义 Policies(范围只是作为声明包装)。

可以在这里找到一本好书:https://leastprivilege.com/2015/12/28/validating-scopes-in-asp-net-4-and-5/

了解后,您希望能够限制某些用户对模块的访问,而不是整个应用程序 - 这可以通过用户声明实现(最常见的实现是 role 声明)。

您可以为每个用户保存一个角色 - AccountManagerStockManager(或两者)。 然后,用至少一个 Scope 定义一个新的 ApiResource,该范围将包含 UserClaims - 您要在其中管理用户检查的声明。

new ApiResource
{
    Name = "rolesResource",
    DisplayName = "Roles",
    Scopes = {
        new Scope
        {
            Name = "roles",
            DisplayName = "User Roles",
            Description = "A list of all the roles assigned to the user",
            Required = true,
            UserClaims =
            {
                JwtClaimTypes.Role
            }
        }
    }
}

然后 - 您的客户可以询问特定的 roles 范围

new Client
{
    ClientId = "your_client_id",
    // More configuration...
     AllowedScopes = {
        // Whatever scopes needed and...
        "roles"
    }
},

然后,当您的客户端请求访问令牌时,它具有相关角色,并且您的控制器/操作可以使用 AuthorizationAttribute 来确保每个用户都具有所需的访问级别。

[Authorize(Roles = "AccountManager")]
public class AccountController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
    }

    [Authorize(Roles = "StockManager")]
    public IActionResult OnlyAccessibleForBothAccountManagerAndStockManager { }
}