经过几十年的使用各种身份验证和授权技术,我的当前MVC应用程序采用以下方法。
声明(Claims)用于所有授权。用户被分配一个角色(多个角色可能是可行的,但我不需要这些)-更多内容如下。
如常规做法一样,使用了ClaimsAuthorize属性类。由于大多数控制器操作都是CRUD,因此我在代码优先数据库生成中编写了一个例程,该例程迭代所有控制器操作并为每个控制器操作属性创建声明类型,例如Read/Edit/Create/Delete。
[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]
为在MVC视图中使用,基础控制器类呈现视图包项目
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();
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)
{
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}
return false;
}
public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}
角色在哪里适用?
我有一个将角色链接到(默认)声明集的表格。在设置用户授权时,默认情况下是给予用户其角色的声明。每个用户可以比默认值拥有更多或更少的声明。为了使编辑简单,声明列表按控制器和操作(在一行中)显示,其他声明则列出。使用一些Javascript按钮选择一组操作以最小化选择声明所需的“点击”次数。保存时,用户的声明将被删除并添加所有选定的声明。Web应用程序仅加载声明一次,因此任何更改都必须在此静态数据内提示重新加载。
因此,管理者可以选择每个角色中包含哪些声明以及在将用户设置为角色和这些默认声明后用户拥有哪些声明。该系统仅有少量用户,因此管理此数据很简单。