数十年来使用了各种身份验证和授权技术后,我当前的MVC应用程序使用以下方法。
索赔用于所有授权。为用户分配了一个角色(可以担任多个角色,但我不需要这个角色)-下面提供了更多信息。
按照惯例,使用ClaimsAuthorize属性类。由于大多数控制器动作都是CRUD,因此我在代码优先的数据库生成中有一个例程,该例程会迭代所有控制器动作,并为读取/编辑/创建/删除的每个控制器动作属性创建声明类型。例如,
[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]
为了在MVC视图中使用,基本控制器类提供了视图包项目
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user claims
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();
// set Viewbag with default authorisations on this controller
ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
}
base.OnActionExecuting(filterContext);
}
对于网站菜单和其他非控制器操作,我还有其他主张。例如,用户是否可以查看特定的货币字段。
bool UserHasSpecificClaim(string claimType, string claimValue)
{
// get user claims
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get the specific claim if any
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}
return false;
}
public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}
那么角色适合在哪里?
我有一张将Role链接到一组(默认)声明的表。设置用户授权时,默认设置是向用户声明其角色。每个用户可以拥有比默认更多或更少的声明。为了简化编辑,通过控制器和操作(连续)显示声明列表,然后列出其他声明。按钮与少量Javascript一起使用,以选择一组操作,以最大程度地减少选择声明所需要的“单击”。在“保存”上,将删除用户声明并添加所有选定的声明。Web应用程序仅加载一次声明,因此任何更改都必须在此静态数据中提示重新加载。
因此,管理者可以在将每个角色设置为角色后选择每个角色中的哪些声明,以及用户具有哪些默认声明以及这些默认声明。该系统只有少数用户,因此管理这些数据非常简单