asp.net - 我可以创建一个自定义授权策略,我可以传递从我的控制器方法接收到的字段吗?
问题描述
我想让我在控制器中从客户端收到的参数用于授权我在我的项目中使用的“POST”方法(用户只能编辑他们分配给的项目)。UserIds 将存在于项目中,因此我需要获取项目并验证当前用户 ID 是否在项目中。
// I want to modify my policy below where I can use "projectId". ProjectId is dynamic and passed in from a ajax call
[Authorize(Policy = "CanModifyProject")]
[HttpPost]
public async Task<IActionResult> SaveWorker(var projectId, workerModel worker)
{
// Code here....
}
我的政策
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanModifyProject requirement)
{
bool isSuperAdmin = context.User.IsAdmin();
bool isAdmin = context.User.IsAdmin();
var currentUserId = context.User.GetUserId();
// I NEED TO HAVE THE DYNAMIC PROJECT ID here recieved by "POST" methods
int projectId = 0;
// Check to see if the project has the assigned User
var projectUserIsAssigned = this.projectRepository.ProjectIsAssignedToUser(projectId currentUserId);
if (isSuperAdmin || isAdmin && projectUserIsAssigned)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
context.Fail();
return Task.CompletedTask;
}
}
如何在我的 post 方法中访问我的 ProjectId ???
解决方案
授权阶段在请求处理管道中相当早,在执行操作之前。所以还没有绑定视图模型(通过模型绑定)。为此,我会使用IActionFilter
or 。IAsyncActionFilter
在那里您可以访问ActionExecutingContext.ActionArguments
以获取您想要的自定义授权的绑定参数。
在这里,我想尝试使用通常在IAuthorizationFilter
or范围内执行的代码以您想要的方式解决它IAsyncAuthorizationFilter
(在AuthorizationMiddleware
. 使用这种方法,获取动作参数值的方式受到限制。它应该可以通过一些键清楚地访问,我们得到的原始值当然是一个字符串。根据您的具体要求,它只是一个参数int
,可以通过客户端的表单数据或查询字符串发送。
这里的重点是我们可以使用CompositeValueProvider
. 代码应该说明一切:
//inject IOptions<MvcOptions> into your CanModifyProject requirement class
//name it as _mvcOptions
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanModifyProject requirement) {
bool isSuperAdmin = context.User.IsAdmin();
bool isAdmin = context.User.IsAdmin();
var currentUserId = context.User.GetUserId();
var projectId = 0;
//get projectId
if(context.Resource is ActionContext ac &&
ac.ActionDescriptor is ControllerActionDescriptor ca)
{
//match only the related controller method
if(ca.ControllerTypeInfo == typeof(YourController) &&
ca.MethodInfo.Name == nameof(YourController.SaveWorker)) {
//create the composite value provider
var valueProvider = await CompositeValueProvider.CreateAsync(ac, _mvcOptions.Value.ValueProviderFactories);
//get the raw id (as string)
var id = valueProvider.GetValue("projectId").FirstValue ?? "";
//parse your projectId here
int.TryParse(id, out projectId);
}
}
//your remaining code (unchanged)
//...
}
推荐阅读
- heroku - Heroku 请求被阻止
- puppeteer - 使用 puppeteer 在浏览器实例上设置 ID
- asp.net - 带有 MVC 文件夹路径/映射的 ASP.NET 核心失败
- android - 无法访问“androidx.navigation.NavArgsLazy”的超类型“kotlin.Lazy”
- 3d - 如何将我的 2D Aim Trainer(内置单游戏)转换为 3D 平台?
- swagger - 在 API Gateway 中聚合来自许多微服务的 OpenAPI 3 (v3/api-docs) 文件
- javascript - 根据传递的类型从函数中获取数据,不使用 if-else 或 switch
- reverse-proxy - CloudFront 反向代理云端
- python - 在 tkinter 和消息编码中出现错误
- python - 使用 cdk 、 sam 和 docker 进行本地测试时,与 aws mysql rds 实例的连接失败