我在.Net Core 3.1 Api中使用基于角色的身份验证。我正在使用Jwt令牌和用户声明。基于角色的身份验证运行良好。但在某些控制器中,我希望确保用户获得他/她自己的数据。因为如果一名员工在请求中发送其他员工id,他/她可以获得资源数据,我不希望这样。
我在令牌中有电子邮件、id和角色以及其他一些数据。
我想要的是类似于[授权(角色="员工",Id={userId}(]
[HttpGet("getUserInventory")]
//[Authorize(Roles="Employee", Claims.Id={userId})]
public IActionResult getUserInventory([FromQuery] int userId)
{
var inventories = _userInventoryExportService.GetGlobalInventory(userId);
if(inventories.Success)
{
return Ok(inventories.Data);
}
return BadRequest(inventories.Message);
}
看看我们在Curity:Securing a.NET Core API上创建的本教程。您将看到如何根据JWT访问令牌中的声明配置授权。
有相同的用例,只授权用户访问自己的邮箱。
控制器:
[HttpPost("{address}/inbox/messages/list")]
[Authorize(Policy = "userAddress")]
public async Task<ActionResult<Response>> ListMessages([FromRoute] string address)
{
// return user mailbox data.
}
这里我定义了userAddress
,以及从url中提取address
字符串的方式。不可能从控制器传递这个值,我不得不从全局请求类中选择它
//Program.cs
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("userAddress", policy =>
{
policy.RequireAssertion(context =>
{
var userAddress = context.User.FindFirst(JWTClaim.Email).Value;
// /api/v1/mailbox/email@example.com/inbox/messages/list
var address = new HttpContextAccessor().HttpContext.Request.RouteValues["address"].ToString();
return address == userAddress;
});
});
});
值得注意的是,context
包含实际的请求值,但不能公开访问,只能通过调试器访问
context.Resource.HttpContext.Request.RouteValues["address"].ToString();