正如你所說,有可能訪問請求的數據OnValidatePrincipal
事件。所以,你可以寫這樣的事情:
OnValidatePrincipal = async (context) =>
{
if (context.Request.Path.Value.StartsWith("/teams/"))
{
var teamId = // get team id from Path;
if (user is not team member)
{
context.Response.StatusCode = 403;
}
}
}
然而,我覺得你的要求與Authorization
而非Authentication
。我會用Policy-Based Authorization
來處理這個要求。例如政策應該是這樣的:
要求和處理程序:
public class TeamMemberHandler: AuthorizationHandler<TeamMemberRequirement>
{
private readonly IActionContextAccessor _accessor; // for getting teamId from RouteData
public TeamMemberHandler(IActionContextAccessor accessor)
{
_accessor = accessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TeamMemberRequirement requirement)
{
var teamId = // get teamId with using _accessor
if (user is not member of team(by teamId))
{
context.Fail();
}
return Task.FromResult(0);
}
}
public class TeamMemberRequirement : IAuthorizationRequirement
{
}
配置服務:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddAuthorization(options =>
{
options.AddPolicy("TeamMember",
policy => policy.Requirements.Add(new TeamMemberRequirement()));
});
services.AddSingleton<IAuthorizationHandler, TeamMemberHandler>();
}
最後使用它在控制器的頂部(或者,如果你願意,你可以在全球範圍添加過濾器)
Authorize[(Policy = "TeamMember")]
public class TeamHomeController : Controller
{
// Authorize[(Policy = "AnotherPolicy")]
public IActionResult Index(){}
}
太棒了,謝謝! 但是,更進一步:參數化策略是否可行?比方說,一個用戶應該聲明他們有權在發送GET'/ some/endpoint?teamId = 3'時讀取一些數據。然後他們嘗試用PUT對同一控制器更新數據。這需要聲稱他們可以更新這些數據。 那麼,是否可以使用這些聲明類型對策略進行參數化?或者,每個人都需要新的政策嗎? – steamrolla
是的,你需要一個新的更新策略,你應該在更新操作方法之上使用它。 –
Bah!這將是一天結束時的一大堆不同的政策,具有相同的代碼但數據不同。也許是來自asp.net核心團隊的增強? – steamrolla