Pan*_*are 7 c# authorization asp.net-core-mvc asp.net-core
在ASP.Net Core中,我们在ConfigureServices方法中定义了授权策略,如下所示.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthorization(options =>
{
options.AddPolicy("Founders", policy =>
policy.RequireClaim ("EmployeeNumber", "1", "2", "3", "4", "5"));
}
}
Run Code Online (Sandbox Code Playgroud)
我们在控制器动作上使用它,如下所示.
[Authorize("Founders")]
public IActionResult GenerateReport()
{
return View();
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好,工作得很好.现在我的问题是,如何在代码中定义"创建者"策略(使用上面代码段中的AddPolicy方法),如何从数据库中添加策略详细信息(名称,声明类型,值)?框架中是否提供了任何钩子,我可以使用它从数据库中填充策略?
这里的想法是我应该能够添加新的员工编号列表(在数据库中),并且应该针对该列表评估策略.遗憾的是,我可以从ConfigureServices本身的数据库中提取此列表,但是在重新启动应用程序之前,不会再获取员工列表的任何新添加内容.任何指针都高度赞赏.
Riz*_*iza 12
您需要结合Requirement和Authorization 处理程序,但不是从数据库填充策略,而是执行您想做的任何身份验证机制。
首先创建一个需求类来提供给策略。让我们暂时命名它ThePolicyRequirement,稍后会详细介绍这个类。其次,创建ThePolicyAuthorizationHandler并将其添加为范围服务
services.AddAuthorization(options =>
{
options.AddPolicy("ThePolicy", policy => policy.Requirements.Add( new ThePolicyRequirement() ));
});
services.AddScoped<IAuthorizationHandler, ThePolicyAuthorizationHandler>();
Run Code Online (Sandbox Code Playgroud)
关键是我们可以在 中注入几乎任何东西ThePolicyAuthorizationHandler,然后我们将这些注入的对象和任何其他可用的对象传递给ThePolicyRequirement,以便它确定用户是否通过身份验证。
例如,这是我ThePolicyAuthorizationHandler的 asp.net core 2 和 3:
public class ThePolicyAuthorizationHandler : AuthorizationHandler<ThePolicyRequirement>
{
readonly AppDbContext _context;
readonly IHttpContextAccessor _contextAccessor;
public ThePolicyAuthorizationHandler(DbContext c, IHttpContextAccessor ca)
{
_context = c;
_contextAccessor = ca;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ThePolicyRequirement 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 (await requirement.Pass(_context, _contextAccessor, area, controller, action, id))
{
context.Succeed(requirement);
}
}
else if (context.Resource is PolicyResource policyResource)
{
var pr = policyResource;
if (await requirement.Pass(_context, _contextAccessor, pr.Area, pr.Controller, pr.Action, pr.Id))
{
context.Succeed(requirement);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
显然更新,.net 5 中的情况有所变化,下面ThePolicyAuthorizationHandler是 .net 5:
public class ThePolicyAuthorizationHandler : AuthorizationHandler<ThePolicyRequirement>
{
readonly AppDbContext _context;
readonly IHttpContextAccessor _contextAccessor;
public ThePolicyAuthorizationHandler(DbContext c, IHttpContextAccessor ca)
{
_context = c;
_contextAccessor = ca;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ThePolicyRequirement 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 (await req.Pass(_context, _contextAccessor, area, controller, action, id))
{
context.Succeed(req);
}
}
if (context.Resource is DefaultHttpContext httpContext)
{
var area = httpContext.Request.RouteValues["area"].ToString();
var controller = httpContext.Request.RouteValues["controller"].ToString();
var action = httpContext.Request.RouteValues["action"].ToString();
var id = httpContext.Request.RouteValues["id"].ToString();
if (await req.Pass(_context, _contextAccessor, area, controller, action, id))
{
context.Succeed(req);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
和我的Requirement班级:
public class ThePolicyRequirement : IAuthorizationRequirement
{
AppDbContext _context;
IHttpContextAccessor _contextAccessor;
public async Task<bool> Pass(AppDbContext context, IHttpContextAccessor contextAccessor, string area, string controller, string action, string id)
{
_context = context;
_contextAccessor = contextAccessor;
//authorization logic goes here
return await Task.FromResult(false);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的示例中,我将 myAppDbContext和HttpContextAssessorto传递给ThePolicyRequirement,但不要传递 theAuthorizationHandlerContext因为在我的情况下,我只需要区域/控制器/操作名称。重要的是我们几乎可以将整个应用程序中可用的任何信息传递给它。
希望这会有所帮助。
| 归档时间: |
|
| 查看次数: |
1762 次 |
| 最近记录: |