将参数从控制器传递到自定义 AuthorizationHandler
Pass Parameter From Controller to Custom AuthorizationHandler
我正在开发一个控制器,它允许人们共享访问更新网站的权限。我正在尝试使用 AuthorizationHandler 来验证当前用户是否有权更新他们正在尝试更新的网站。
我当前的 Request 和 AuthorizationHandler
public class WebsiteRequirement : IAuthorizationRequirement
{
public WebsiteRequirement(int websiteId)
{
WebsiteId = websiteId;
}
public int WebsiteId { get; private set; }
}
internal class WebsiteAuthorizationHandler : AuthorizationHandler<WebsiteRequirement>, IAuthorizationHandler
{
private readonly IWebsiteLogic _websiteLogic;
public WebsiteAuthorizationHandler(IWebsiteLogic websiteLogic)
{
_websiteLogic = websiteLogic;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, WebsiteRequirement requirement)
{
int userId = int.Parse(context.User.FindFirst(c => c.Type == "UserId").Value);
// Use the _websiteLogic to check if user has access, based on user id and website Id
if(_websiteLogic.CheckUserAccess(userId, requirement.WebsiteId)){
context.Succeed(requirement);
}
else
{
context.Fail();
}
return Task.CompletedTask;
}
}
我知道您可以使用 AuthorizationHandler 创建相当动态的策略,如下所示
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("WebAuth", policy => policy.Requirements.Add(new WebsiteRequirement(1)));
});
services.AddSingleton<IAuthorizationHandler, WebsiteAuthorizationHandler>();
}
但是是否可以从控制器传递 1
?我不想为每个新网站都创建一个新策略(我也想为各种其他类似用例重用这个类似的结构。我最后的办法是有一个 SecurityService ,我每次调用控制器,但这确实看起来并不优雅,但我也没有看到任何允许我尝试做的事情。
[HttpPost]
[Authorize(Policy = "WebAuth", WebsiteId=[FromBody]website.id)] // Trying to do something like this
public ActionResult<WebsiteDto> SaveWebsite([FromBody] WebsiteDto website)
{
if(_websiteLogic.CheckUserAccess(CurrentUserId, website.Id)) // My Backup Solution
{
return _websiteLogic.AddWebsite(website);
}
return new UnauthorizedResult();
}
如果您尝试从 HTTP 请求中传递值,那么您可以通过传递到处理程序的 AuthorizationHandlerContext
Resource
属性 访问这些值(source).
如果您只是想传递一些配置类型设置,那么请确保您的 AuthorizationHandler
具有生命周期 Transient 并将这些值传递给构造函数。
我正在开发一个控制器,它允许人们共享访问更新网站的权限。我正在尝试使用 AuthorizationHandler 来验证当前用户是否有权更新他们正在尝试更新的网站。
我当前的 Request 和 AuthorizationHandler
public class WebsiteRequirement : IAuthorizationRequirement
{
public WebsiteRequirement(int websiteId)
{
WebsiteId = websiteId;
}
public int WebsiteId { get; private set; }
}
internal class WebsiteAuthorizationHandler : AuthorizationHandler<WebsiteRequirement>, IAuthorizationHandler
{
private readonly IWebsiteLogic _websiteLogic;
public WebsiteAuthorizationHandler(IWebsiteLogic websiteLogic)
{
_websiteLogic = websiteLogic;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, WebsiteRequirement requirement)
{
int userId = int.Parse(context.User.FindFirst(c => c.Type == "UserId").Value);
// Use the _websiteLogic to check if user has access, based on user id and website Id
if(_websiteLogic.CheckUserAccess(userId, requirement.WebsiteId)){
context.Succeed(requirement);
}
else
{
context.Fail();
}
return Task.CompletedTask;
}
}
我知道您可以使用 AuthorizationHandler 创建相当动态的策略,如下所示
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("WebAuth", policy => policy.Requirements.Add(new WebsiteRequirement(1)));
});
services.AddSingleton<IAuthorizationHandler, WebsiteAuthorizationHandler>();
}
但是是否可以从控制器传递 1
?我不想为每个新网站都创建一个新策略(我也想为各种其他类似用例重用这个类似的结构。我最后的办法是有一个 SecurityService ,我每次调用控制器,但这确实看起来并不优雅,但我也没有看到任何允许我尝试做的事情。
[HttpPost]
[Authorize(Policy = "WebAuth", WebsiteId=[FromBody]website.id)] // Trying to do something like this
public ActionResult<WebsiteDto> SaveWebsite([FromBody] WebsiteDto website)
{
if(_websiteLogic.CheckUserAccess(CurrentUserId, website.Id)) // My Backup Solution
{
return _websiteLogic.AddWebsite(website);
}
return new UnauthorizedResult();
}
如果您尝试从 HTTP 请求中传递值,那么您可以通过传递到处理程序的 AuthorizationHandlerContext
Resource
属性 访问这些值(source).
如果您只是想传递一些配置类型设置,那么请确保您的 AuthorizationHandler
具有生命周期 Transient 并将这些值传递给构造函数。