问题描述
我在 .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 中的自定义表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!