簡體   English   中英

具有范圍特定路由的 C# Web API

[英]C# Web API with Scope Specific Routes

我使用 IdentityServer4 作為身份提供者,我的 C# Web API(用於用戶)通過以下方式保護:

services.AddAuthentication(Authentication.Bearer)
  .AddJwtBearer(Authentication.Bearer, options =>
  {
    options.Authority = Configuration.GetSection("IdentityServer:Authority").Value;
    options.Audience = Scopes.UsersService;
  });

和控制器上的[Authorize] 因此,任何想要在 UsersService 中調用路由的人都需要一個以“usersservice”為范圍的經過驗證的令牌。

我想通過范圍開辟幾條路線。 因此,如果路由調用者具有“usersservice”范圍,他們仍然可以訪問所有路由。 但是,如果他們具有“usersservice.read”范圍,他們將只能訪問我指定用於讀取訪問的路由。 我怎樣才能做到這一點?

解決方案

Alpha75 列出了一系列關於如何解決此問題的選項。 我最終選擇了 AddPolicy 路線。 這就是我為我的用戶服務實現它的方式。 我去掉了“userservice”作用域,增加了兩個作用域“usersservice.all”和“usersservice.read”,而不是單純的依賴觀眾。

services.AddAuthentication(Authentication.Bearer)之后的 Startup.cs 中:

services.AddAuthorization(options =>
  options.AddPolicy("all", policy =>
    policy.RequireClaim("scope", "usersservice.all")
    )
  );

services.AddAuthorization(options =>
  options.AddPolicy("read", policy => 
    policy.RequireClaim("scope", "usersservice.all", "usersservice.read")
    )
  );

然后在讀取操作上,我有[Authorize(Policy = "read")]並且在所有其他操作上,我有[Authorize(Policy = "all")] 注意:“usersservice.all”在“讀取”策略中,因此任何具有 all 范圍的調用者也可以訪問讀取操作。

api

一件事是 Api 資源,另一件事是 Api 資源的 Api 范圍。 在您的 API 處理程序中,您必須配置您的 Api 資源。

options.Audience = "usersservice";

要按范圍保護,您可以使用幾種方法

  • 保護動作方法:

     [HttpGet] [RequiredScope("usersservice.write")] public IEnumerable<TodoItem> Get() { // Do the work and return the result. // ... }
  • 保護控制器:

     [Authorize] [RequiredScope("usersservice.read")] public class TodoListController : Controller { ... }
  • 有條件地使用擴展方法 VerifyUserHasAnyAcceptedScope

     [HttpGet] public IEnumerable<TodoItem> Get() { HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); // Do the work and return the result. // ... }
  • 基於政策( Duende 文檔中的示例):

     // 1. In ConfigureServices services.AddAuthorization(options => { options.AddPolicy("read_access", policy => policy.RequirementClaim("scope", "usersservice.read"); }); // 2.a. In the Controller declaratively [Authorize("read_access")] public async Task<IActionResult> Get() { // rest omitted } // 2.b. Or In the Controller imperatively public class DataController : ControllerBase { IAuthorizationService _authz; public DataController(IAuthorizationService authz) { _authz = authz; } public async Task<IActionResult> Get() { var allowed = _authz.CheckAccess(User, "read_access"); // rest omitted } }
  • 基於策略但使用自定義要求 這比其他人更靈活,但如果您只想檢查范圍,則可能沒有必要。

身份服務器配置

根據 IdentityServer4 版本,您將對關系 ApiResource <-> ApiScope 有不同的模型:

...從 v4 開始,范圍有自己的定義,並且可以有選擇地被資源引用。 在 v4 之前,范圍始終包含在資源中。

IdentityServer4 文檔

如果你使用 v4,你可以有這樣的配置(你可能會有一個帶有你的配置的數據庫):

public static IEnumerable<ApiScope> GetApiScopes()
{
    return new List<ApiScope>
    {
        // userservice API specific scopes
        new ApiScope(name: "usersservice.read",   displayName: "Reads user data"),
        new ApiScope(name: "usersservice.write",    displayName: "Writes user data"),

        // another API specific scopes
        new ApiScope(name: "another.read",    displayName: "Reads another data"),            

        // shared scope
        new ApiScope(name: "manage", displayName: "Provides administrative access to user and another data")
    };
}

public static readonly IEnumerable<ApiResource> GetApiResources()
{
    return new List<ApiResource>
    {
        new ApiResource("usersservice", "Users Service API")
        {
            Scopes = { "usersservice.read", "usersservice.write", "manage" }
        },

        new ApiResource("anotherservice", "Another API")
        {
            Scopes = { "another.read", "manage" }
        }
    };
}

請注意,使用此模型,您可以在資源之間“共享”范圍,盡管它是可選的。 在示例中,范圍“管理”允許訪問這兩個服務。 這在 v4 之前是不可能的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM