使用ASP.NET MVC进行基于声明的授权

Rom*_*lla 5 authentication authorization claims-based-identity asp.net-mvc-4

我正在阅读很多博客文章和stackoverflow答案,但我仍然无法找到一个使用基于声明的身份验证和授权的真实世界开源项目,以便我可以了解如何实际实现这些.

到目前为止,我能找到的是Thinktecture.IdentityModel这个博客在示例网站上实现基于声明的授权.如果你们可以指出一些使用声明的开源项目,那将非常有帮助.

我感兴趣的是如何使用数据库检索我的应用程序的声明.

到目前为止,我曾尝试是在内存中的权利要求商店使用模拟databsae,我创建了一个CustomClaimsTransformerCustomAuthorisationManager这个样子.

public class CustomClaimsTransformer : ClaimsAuthenticationManager
    {
        public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
            //validate name claim
            string nameClaimValue = incomingPrincipal.Identity.Name;

            return CreatePrincipal(nameClaimValue);
        }

        private ClaimsPrincipal CreatePrincipal(string userName)
        {
            int userId = ClaimStore.Users.First(u => u.Value == userName).Key;
            var claims = ClaimStore.ClaimsSet.Where(c => c.Key == userId);

            var claimsCollection = claims.Select(kp => kp.Value).ToList();

            return new ClaimsPrincipal(new ClaimsIdentity(claimsCollection, "Custom"));
        }
    }

public class CustomAuthorisationManager : ClaimsAuthorizationManager
    { 
        public override bool CheckAccess(AuthorizationContext context)
        {
            string resource = context.Resource.First().Value;
            string action = context.Action.First().Value;

            if (action == "Show" && resource == "Code")
            {
                bool likesJava = context.Principal.HasClaim(ClaimStore._httpMyclaimsUsers, "True");
                return likesJava;
            }
            else if (action == "Read" && resource == "Departments")
            {
                bool readDeps = context.Principal.HasClaim(ClaimStore._httpMyclaimsDepartments, "Read");
                return readDeps;
            }
            return false;
        }
    }
Run Code Online (Sandbox Code Playgroud)

如何在没有太多IF条件的情况下在现实场景中实现这些?

Rom*_*lla 0

我最终成功地使用现有的 ASP.NET Identity 2.0 表和一些我自己的表来设计具有所需功能的自己的系统。

我将把每个 AREA-CONTROLLER-ACTION 三人组称为我系统中的资源。包括 WebAPI。区域本身就是一种资源。控制器本身就是一种资源。行动本身就是一种资源。它们的任意组合也是一种资源。我将使用反射从系统本身自动生成所有内容。

另外,我将使用同一个AspNetRoles表来存储我的用户组。用户属于一个或多个组(超级管理员、管理员、代理、客户等)。

使用现有的基于角色的模型作为带有声明的基于用户组的模型,我可以让它工作。超级管理员处于上帝模式。他们可以创建较低级别的用户/组/分配权限等。

用户可以拥有特殊权限。例如,代理组中的每个人都被拒绝更新酒店,但也可能是酒店所有者的特殊代理可以被授予仅更新其酒店的特定访问权限。

由于整个门禁系统运行在MVC区域控制器动作集上。最初没有人没有访问权限(包括超级管理员),我们逐渐定义组/用户可以访问哪些部分。我们通过声明为超级管理员和管理员提供独占访问权限。默认情况下,对任何地方的访问都被拒绝。

自动生成 AREA-CONTROLLER-ACTION 集后,我让用户选择哪个组有权访问哪个项目。

当用户登录时,我获取当前用户有权访问的所有资源并将它们存储为声明。基于此,使用声明身份验证管理器,当用户请求访问某些资源时,我可以检查他们的声明并决定是否应该授予他们访问权限。

foreach(var claim in permissionClaims) {
    var parts = claim.Value.Split(new [] {
        '|'
    }, StringSplitOptions.None);
    if (parts.Length == 3) {
        //var httpMethod = parts[0];
        var action = parts[1]; 
        var api = parts[2];
        //Current.Log.Warn("Checking Access : " + req + " [action: " + action + "]");
        // is this request for a API action?
        if (api.Contains("API")) {
            // if so, req must be for a API action
            if (req.Contains("Api") && action.Contains(req)) {
                Log.Trace("User has access to API : " + req + " [action: " + action + "]");
                return true;
            }
        } else {
            // this is for a MVC action
            if (action.Contains(req)) {
                Log.Trace("User has access to MVC : " + req + " [action: " + action + "]");
                return true;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经在这里详细解释了该方法- ASP.NET MVC 细粒度身份和访问控制