您可以参考Derek Greer 对Dot Net core的这个SO 问题的回答,另外我将在下面重申答案 -
ASP.Net Core 团队推荐的方法是使用此处完整记录的新策略设计。新方法背后的基本思想是使用新的 [Authorize] 属性来指定“策略”(例如 [Authorize(Policy = "YouNeedToBe18ToDoThis")],其中策略在应用程序的 Startup.cs 中注册以执行某些块代码(即确保用户有年龄声明,其中年龄为 18 岁或以上)。
策略设计是对框架的一个很好的补充,应该赞扬 ASP.Net 安全核心团队的引入。也就是说,它并不适合所有情况。这种方法的缺点是它无法为简单地断言给定控制器或动作需要给定声明类型的最常见需求提供方便的解决方案。在应用程序可能具有数百个离散权限管理单个 REST 资源(“CanCreateOrder”、“CanReadOrder”、“CanUpdateOrder”、“CanDeleteOrder”等)上的离散权限的情况下,新方法要么需要重复的一对一策略名称和声明名称之间的一个映射(例如 options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));),或编写一些代码在运行时执行这些注册(例如,从数据库中读取所有声明类型并在循环中执行上述调用)。在大多数情况下,这种方法的问题在于它是不必要的开销。
虽然 ASP.Net Core 安全团队建议永远不要创建自己的解决方案,但在某些情况下,这可能是开始时最谨慎的选择。
下面是一个实现,它使用 IAuthorizationFilter 提供一种简单的方法来表达给定控制器或操作的声明要求:
public class ClaimRequirementAttribute : TypeFilterAttribute
{
public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter))
{
Arguments = new object[] {new Claim(claimType, claimValue) };
}
}
public class ClaimRequirementFilter : IAuthorizationFilter
{
readonly Claim _claim;
public ClaimRequirementFilter(Claim claim)
{
_claim = claim;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value);
if (!hasClaim)
{
context.Result = new ForbidResult();
}
}
}
[Route("api/resource")]
public class MyController : Controller
{
[ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")]
[HttpGet]
public IActionResult GetResource()
{
return Ok();
}
}
.NET Framework的部分答案-
推荐的自定义属性类:
public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
private readonly PermissionAction[] permissionActions;
public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
{
this.permissionActions = permissionActions;
}
protected override Boolean IsAuthorized(HttpActionContext actionContext)
{
var currentIdentity = actionContext.RequestContext.Principal.Identity;
if (!currentIdentity.IsAuthenticated)
return false;
var userName = currentIdentity.Name;
using (var context = new DataContext())
{
var userStore = new UserStore<AppUser>(context);
var userManager = new UserManager<AppUser>(userStore);
var user = userManager.FindByName(userName);
if (user == null)
return false;
foreach (var role in permissionActions)
if (!userManager.IsInRole(user.Id, Convert.ToString(role)))
return false;
return true;
}
}
}