gpt4 book ai didi

asp.net - asp.net 核心策略和声明可以处理基于资源/事件的授权吗?

转载 作者:行者123 更新时间:2023-12-02 04:40:08 24 4
gpt4 key购买 nike

我正在研究 asp.net core 以及新的安全策略和声明功能。刚刚看过它后,我看不出它比过去现有的授权属性逻辑好多少,在过去,硬编码角色或用户被装饰在 Controller 、方法等上。对我来说,问题刚刚从硬-将属性编码为硬编码策略。

理想情况下,我想执行基于事件/资源的授权,其中一切都由数据库驱动。每个事件或资源都将存储在数据库中,并且将为该资源分配权限/角色。

在研究该主题时,我发现 Stefan Wloch 的这篇精彩文章几乎完全涵盖了我想要做的事情。

http://www.codeproject.com/Articles/1079552/Custom-Roles-Based-Access-Control-RBAC-in-ASP-NE

所以我的问题是新的核心功能如何防止我们在需要更改允许哪些角色/权限访问 Controller 或 Controller 中的方法时进行硬编码和重新编译?我了解如何使用 claims 来存储任何东西,但 policy 部分似乎容易发生变化,这让我们回到原点。不要误会我的意思,我喜欢 asp.net core 和所有巨大的变化,只是在寻找有关如何处理授权的更多信息。

最佳答案

在实现您想要的内容时,至少需要考虑两件事。第一个是如何在数据库中对 Controller-Action 访问建模,第二个是在 asp.net core Identity 中应用该设置。

第一个,有太多的可能性取决于应用程序本身,所以让我们创建一个名为 IActivityAccessService 的服务接口(interface)来封装。我们通过依赖项注入(inject)来使用该服务,以便我们可以向其中注入(inject)我们需要的任何内容。

对于第二种,可以通过在基于策略的授权中自定义AuthorizationHandler来实现。第一步是在 Startup.ConfigureServices 中进行设置:

services.AddAuthorization(options =>
{
options.AddPolicy("ActivityAccess", policy => policy.Requirements.Add( new ActivityAccessRequirement() ));
});
services.AddScoped<IAuthorizationHandler, ActivityAccessHandler>();
//inject the service also
services.AddScoped<IActivityAccessService, ActivityAccessService>();
//code below will be explained later
services.AddHttpContextAccessor();

接下来我们创建ActivityAccessHandler:

public class ActivityAccessHandler : AuthorizationHandler<ActivityAccessRequirement>
{
readonly IActivityAccessService _ActivityAccessService;

public ActivityAccessHandler (IActivityAccessService r)
{
_ActivityAccessService = r;
}

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext authHandlerContext, ActivityAccessRequirement requirement)
{
if (context.Resource is AuthorizationFilterContext filterContext)
{
var area = (filterContext.RouteData.Values["area"] as string)?.ToLower();
var controller = (filterContext.RouteData.Values["controller"] as string)?.ToLower();
var action = (filterContext.RouteData.Values["action"] as string)?.ToLower();
var id = (filterContext.RouteData.Values["id"] as string)?.ToLower();
if (_ActivityAccessService.IsAuthorize(area, controller, action, id))
{
context.Succeed(requirement);
}
}
}
}

public class ActivityAccessRequirement : IAuthorizationRequirement
{
//since we handle the authorization in our service, we can leave this empty
}

因为我们可以在 AuthorizationHandler 中使用依赖注入(inject),所以我们在这里注入(inject) IActivityAccessService

现在我们可以访问正在请求的资源,我们需要知道是谁在请求它。这可以通过注入(inject) IHttpContextAccessor 来完成。于是在上面的代码中加入了services.AddHttpContextAccessor(),就是这个原因。

对于 IActivityAccessService,您可以执行如下操作:

public class ActivityAccessService : IActivityAccessService
{
readonly AppDbContext _context;
readonly IConfiguration _config;
readonly IHttpContextAccessor _accessor;
readonly UserManager<AppUser> _userManager;

public class ActivityAccessService(AppDbContext d, IConfiguration c, IHttpContextAccessor a, UserManager<AppUser> u)
{
_context = d;
_config = c;
_accessor = a;
_userManager = u;
}

public bool IsAuthorize(string area, string controller, string action, string id)
{
//get the user object from the ClaimPrincipals
var appUser = await _userManager.GetUserAsync(_accessor.HttpContext.User);
//get user roles if necessary
var userRoles = await _userManager.GetRolesAsync(appUser);
// all of needed data are available now, do the logic of authorization
return result;
}
}

请注意,上面 IsAuthorize 正文中的代码是示例。虽然它会起作用,但人们可能会说这不是一个好的做法。但是由于 IActivityAccessService 只是一个普通的简单服务类,我们可以向它注入(inject)我们需要的任何东西,并以我们想要的任何方式修改 IsAuthorize 方法签名。例如,我们可以只传递 filterContext.RouteData

至于如何将其应用于 Controller 或操作:

[Authorize(Policy = "ActivityAccess")] 
public ActionResult<IActionResult> GetResource(int resourceId)
{
return Resource;
}

希望对你有帮助

关于asp.net - asp.net 核心策略和声明可以处理基于资源/事件的授权吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38216016/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com