問題描述
我在 .Net 2.1 框架上使用 ASP.Net Core Web Api 2我有自定義 AppUsers 和 AppRoles 表,與橋接表 AppUserRoles 鏈接
I am using ASP.Net Core Web Api 2 on .Net 2.1 Framework I have custom AppUsers and AppRoles tables, linked with bridge table AppUserRoles
我的主要問題是我想使用 [Authorize(Roles = "UserRole")]
由于 User.Identity 工作正常并且我從 User.Identity.Name
獲取用戶 ID,我認為有一些方法可以在控制器請求之前設置角色并檢查它們,或者使用 User.IsInRole("UserRole")
用于檢查控制器內部.
My main problem is that I want to use [Authorize(Roles = "UserRole")]
As User.Identity is working fine and I am getting user Id from User.Identity.Name
I thought there was some way to set roles and check them before controller request, or to use User.IsInRole("UserRole")
for checking inside controller.
是否可以以某種方式重建或重載 .IsInRole("UserRole")
函數或 [Authorize(Roles = "UserRole")]
屬性背景函數,所以我可以編寫我自己的邏輯來檢查用戶權限嗎?或者將我的表設置為要使用的默認表,這樣它就可以在自邏輯上工作.對于我的任務,速度和安全性一樣重要.
Is it possible to rebuild or overload .IsInRole("UserRole")
function or [Authorize(Roles = "UserRole")]
attribute background function somehow, so I could write my own logic to check user permissions? Or to set my tables as default tables to use, so it could work on self logic.
For my task, speed matters as much as security.
如果有其他方法,我愿意接受建議,但我的意思是更好地理解這些功能.
I am open to suggestions, if there is some other way, but my point also is to get better understanding in those functions.
推薦答案
您不需要重寫 Authorize 或 IsInRole.只需將角色作為聲明添加到 User.Identity.您可以使用中間件進行聲明轉換.
You don't need to override Authorize or IsInRole. Just add the roles as claim to the User.Identity. You can use middleware to do the claims transformation.
作為一個例子,我建議你看看 PolicyServer.它具有相同的方法.免費 OSS 版本在中間件中增加了聲明.
As an example I suggest you take a look at the PolicyServer. It has the same approach. The free OSS version adds claims in the middleware.
/// Add the policy server claims transformation middleware to the pipeline.
/// This middleware will turn application roles and permissions into claims
/// and add them to the current user
public static IApplicationBuilder UsePolicyServerClaims(this IApplicationBuilder app)
{
return app.UseMiddleware<PolicyServerClaimsMiddleware>();
}
PolicyServerClaimsMiddleware 在哪里:
Where PolicyServerClaimsMiddleware is:
public class PolicyServerClaimsMiddleware
{
private readonly RequestDelegate _next;
/// <summary>
/// Initializes a new instance of the <see cref="PolicyServerClaimsMiddleware"/> class.
/// </summary>
/// <param name="next">The next.</param>
public PolicyServerClaimsMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary>
/// Invoke
/// </summary>
/// <param name="context">The context.</param>
/// <param name="client">The client.</param>
/// <returns></returns>
public async Task Invoke(HttpContext context, IPolicyServerRuntimeClient client)
{
if (context.User.Identity.IsAuthenticated)
{
var policy = await client.EvaluateAsync(context.User);
var roleClaims = policy.Roles.Select(x => new Claim("role", x));
var permissionClaims = policy.Permissions.Select(x => new Claim("permission", x));
var id = new ClaimsIdentity("PolicyServerMiddleware", "name", "role");
id.AddClaims(roleClaims);
id.AddClaims(permissionClaims);
context.User.AddIdentity(id);
}
await _next(context);
}
}
從啟動開始:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore(options =>
{
// workaround: https://github.com/aspnet/Mvc/issues/7809
options.AllowCombiningAuthorizeFilters = false;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddAuthorization();
// This is not relevant for you, but just to show how policyserver is implemented.
// The bottom line is that you can implement this anyway you like.
// this sets up the PolicyServer client library and policy
// provider - configuration is loaded from appsettings.json
services.AddPolicyServerClient(Configuration.GetSection("Policy"))
.AddAuthorizationPermissionPolicies();
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
// add this middleware to make roles and permissions available as claims
// this is mainly useful for using the classic [Authorize(Roles="foo")] and IsInRole functionality
// this is not needed if you use the client library directly or the new policy-based authorization framework in ASP.NET Core
app.UsePolicyServerClaims();
app.UseMvc();
}
該示例從文件中讀取配置,這也可能是您的一個選項.但是你也可以實現一個 store 并添加一些緩存.
The example reads the configuration from file, which may be an option for you as well. But you can also implement a store and add some caching.
如果您想添加一些授權邏輯,那么我建議您創建一些策略和授權處理程序.只需確保在正確的位置使用中間件即可.
If you want to add some authorization logic then I suggest you create some policies and authorization handlers. Just make sure that you use the middleware at the right place.
另一種方法是使用您自己的過濾器/屬性:
An alternative is to use your own filter / attribute:
//using Microsoft.AspNetCore.Authorization;
//using Microsoft.AspNetCore.Mvc;
//using Microsoft.AspNetCore.Mvc.Filters;
public class CustomPolicyAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
private int _number;
public CustomPolicyAttribute(int number)
{
_number = number;
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var service = (IAuthorizationService)context.HttpContext.RequestServices.GetService(typeof(IAuthorizationService));
var requirement = new CustomRequirement
{
Number = _number
};
var result = await service.AuthorizeAsync(context.HttpContext.User, null, requirement);
if (!result.Succeeded)
context.Result = new ForbidResult();
}
}
您可以通過多種方式使用它.用作屬性(Authorize 等效項):
You can use this in a couple of ways. Use as attribute (the Authorize equivalent):
[CustomPolicy(1)]
public async Task<IActionResult> DoSomething()
{
}
或手動驗證(IsInRole 等效項):
Or validate manually (the IsInRole equivalent):
public class MyController : Controller
{
private readonly IAuthorizationService _authorizationService;
public MyController(IAuthorizationService authorizationService)
{
_authorizationService = authorizationService;
}
public async Task<IActionResult> DoSomething(int number)
{
var requirement = new CustomRequirement
{
Number = number
};
var result = await _authorizationService.AuthorizeAsync(User, null, requirement);
if (!result.Succeeded) return Forbid();
return View("success");
}
}
您將需要一個 AuthorizationHandler 來評估需求:
You will need an AuthorizationHandler to evaluate the requirement:
public class CustomRequirementHandler : AuthorizationHandler<CustomRequirement>
{
// Use dependency injection to include services you need.
public CustomRequirementHandler ()
{
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
{
// Add your advanced check here.
if (requirement.Number > 0)
{
context.Succeed(requirement);
}
}
}
并在啟動時注冊:
services.AddTransient<IAuthorizationHandler, CustomRequirementHandler>();
在處理程序中,您可以添加自己的邏輯.在這種情況下,您不必添加策略,也不必將授權添加為聲明.
In the handler you can add your own logic. In that case you won't have to add policies and you don't have to add authorization as claims.
這篇關于ASP.Net Identity 內置函數與 ASP.Net Core 中的自定義表的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!