[英]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 之前,范圍始終包含在資源中。
如果你使用 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.