几十年来使用了各种身份验证和授权技术,我当前的 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");
}
}
那么角色在哪里适合呢?
我有一个将角色链接到一组(默认)声明的表。设置用户授权时,默认是给用户他们角色的声明。每个用户可以拥有比默认更多或更少的声明。为了简化编辑,声明列表按控制器和操作(连续)显示,然后列出其他声明。按钮与一些 Javascript 一起使用来选择一组操作,以最大限度地减少选择声明所需的“点击”。保存时,将删除用户声明并添加所有选定的声明。 Web 应用程序仅加载一次声明,因此任何更改都必须提示重新加载此静态数据。
因此,经理可以选择每个角色中的哪些声明以及用户在将其设置为角色后拥有哪些声明以及这些默认声明。该系统只有少量用户,因此管理这些数据很简单