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

时间:2014-02-16 05:00:46

标签: asp.net-mvc-4 authentication authorization claims-based-identity

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

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

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

到目前为止,我尝试的是使用内存声明存储来模拟数据库,我已经创建了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;
        }
    }

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

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分: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;
            }
        }
    }
}

我已详细解释了这种方法here - ASP.NET MVC Fine Grained Identity & Access Control