如何使用ASP.NET标识使声明无效?

时间:2014-02-12 22:37:28

标签: asp.net asp.net-mvc asp.net-mvc-5 claims-based-identity asp.net-identity

我刚刚将一些应用程序升级到ASP.NET MVC 5.我已经使用ASP.NET Membership几年了,并且正在探索切换到ASP.NET身份的可能性。

我正在构建一个小测试应用程序并且我已经使用身份验证(针对活动目录和自定义SQL Server架构,具体取决于用户),甚至通过在签名之前向ClaimsIdentity添加角色声明进行授权用户(显然开箱即用的Authorize属性实际上会违反所提供的任何索赔信息)。

默认情况下,声明存储在身份验证Cookie中很酷。但是,当有关用户的信息发生变化(即在角色中添加或删除它们)时,这会产生问题。

显然,我可以像往常一样滚动自己的Authorize属性。如果我这样做,我只会一起跳过索赔,只需根据请求检查数据库中的角色。

有没有办法在ASP.NET身份中使用声明并知道它们何时不再有效?框架是否提供了解决此问题的任何选项?

2 个答案:

答案 0 :(得分:2)

您可能想看看这个问题/答案,了解如何自动解决这个问题:

What is the SecurityStamp used for?

答案 1 :(得分:0)

我最近在项目中实现了基于声明的功能集。我发现Identity没有提供物理更新用户声明的机制。 MS构建它的方式似乎必须从用户中删除声明,因此当自定义授权属性被命中时,它将看到用户没有声明因此不会通过。我必须构建它的方式是实现一个单独的基本声明实用程序与视图和控制器来管理我的自定义声明,例如当我创建一个新用户我分配了各种声明给用户。我还有一个扩展的或自定义的Identity Manager类,我与之交互以管理我的用户声明,密码,锁定帐户添加新角色和删除角色。 在我的观点Side我创建了一个自定义HTML.Helper扩展方法,以帮助验证允许用户访问或不访问的内容。下面是一些代码示例。

Identity Manager类

public class IdentityManager
    {
        private RoleManager<IdentityRole> _roleManager;
        private UserManager<ApplicationUser> _userManager;
        private ApplicationDbContext _dbContext;
        private ApplicationSignInManager _signInManager;
        private DpapiDataProtectionProvider protectionProvider;


        public IdentityManager()
        {
            _dbContext = new ApplicationDbContext();
            _roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(_dbContext));
            _userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(_dbContext));
            protectionProvider = new DpapiDataProtectionProvider("Demo");
            _userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(protectionProvider.Create("ResetTokens"));
        }
        public IdentityManager(ApplicationSignInManager signmanager)
        {
            _dbContext = new ApplicationDbContext();
            _signInManager = signmanager;
            _roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(_dbContext));
            _userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(_dbContext));
            protectionProvider = new DpapiDataProtectionProvider("Demo");
            _userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(protectionProvider.Create("ResetTokens"));
        }

        public ApplicationSignInManager SignInManager
        {
            get
            {
                return _signInManager;
            }
            private set { _signInManager = value; }
        }

        public bool CreateNewUserRole(string role)
        {
            if (!RoleExist(role))
            {
                var result = _roleManager.Create(new IdentityRole(role));

                return result.Succeeded;
            }
            return false;
        }

        public bool DeleteUserRole(string role)
        {
            if (!RoleExist(role))
                return true;

            var result = _roleManager.Delete(new IdentityRole(role));
            return result.Succeeded;
        }

        public IdentityResult DeleteMemberShipUser(ApplicationUser user)
        {
            return _userManager.Delete(user);
        }

        public bool DeleteAllUtilityUsers(int utilityid)
        {
            try
            {
                var users = _dbContext.Users.Where(u => u.UtilityId == utilityid).ToList();

                foreach (var user in users)
                {
                    DeleteMemberShipUser(user);
                }
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        public bool RoleExist(string role)
        {
            return _roleManager.RoleExists(role);
        }

        public IdentityResult ChangePassword(ApplicationUser user, string token, string newpassword)
        {
            _userManager.UserValidator = new UserValidator<ApplicationUser>(_userManager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };
            return _userManager.ResetPassword(user.Id, token, newpassword);
        }

        public ApplicationUser GetUserByIdentityUserId(string userId)
        {
            return _userManager.FindById(userId);
        }
        public IdentityResult CreateNewUser(ApplicationUser user, string password)
        {
            _userManager.UserValidator = new UserValidator<ApplicationUser>(_userManager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };

            _userManager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = false,
                RequireDigit = false,
                RequireLowercase = false,
                RequireUppercase = false,
            };

            // Configure user lockout defaults
            _userManager.UserLockoutEnabledByDefault = false;
            _userManager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
            _userManager.MaxFailedAccessAttemptsBeforeLockout = 5;

            var result = _userManager.Create(user, password);
            return result;
        }

        public IdentityResult UpdateUser(ApplicationUser user)
        {
            return _userManager.Update(user);
        }

        public bool AddUserToRole(string userId, string roleName)
        {
            var result = _userManager.AddToRole(userId, roleName);
            return result.Succeeded;
        }

        public bool RemoveUserFromRole(string userId, string role)
        {
            var result = _userManager.RemoveFromRole(userId, role);
            return result.Succeeded;
        }

        public IList<string> GetUserRoles(string userid)
        {
            return _userManager.GetRoles(userid);
        }

        public string GetUserRole(string userid)
        {
            return _userManager.GetRoles(userid).FirstOrDefault();
        }

        public IdentityRole GetRoleByRoleName(string roleName)
        {
            return _roleManager.Roles.First(i => i.Name == roleName);
        }

        public string GetUserRoleId(string userId)
        {
            var userRole = GetUserRole(userId);
            if (string.IsNullOrWhiteSpace(userRole)) return null;

            var role = GetRoleByRoleName(userRole);
            return role.Id;
        }

        public IdentityResult CreateNewSystemRole(IdentityRole role)
        {
            return !RoleExist(role.Name) ? _roleManager.Create(role) : new IdentityResult(new List<string> { "Role Already Exists" });
        }

        public List<IdentityRole> GetAllRoles()
        {
            return _roleManager.Roles.ToList();
        }

        public bool IsUserInRole(string role, string userName)
        {
            var user = _userManager.FindByName(userName);
            return _userManager.IsInRole(user.Id, role);
        }

        public ApplicationUser GetUserByUserName(string username)
        {
            return _userManager.FindByName(username);
        }

        public string GenerateResetToken(string userid)
        {
            return _userManager.GeneratePasswordResetToken(userid);
        }

        public IdentityResult SetLockStatus(string userid, bool lockstatus)
        {
            return _userManager.SetLockoutEnabled(userid, lockstatus);
        }

        public IdentityResult AddUserClaim(string userId, Claim claim)
        {
            return _userManager.AddClaim(userId, claim);
        }

        public void AddRoleClaim(string roleId, string claimType, string claimValue, int utilityid, string description)
        {
            try
            {
                _userManager.UserValidator = new UserValidator<ApplicationUser>(_userManager)
                {
                    AllowOnlyAlphanumericUserNames = false,
                    RequireUniqueEmail = true
                };

                var roleClaim = new AspNetRoleClaims()
                {
                    RoleId = roleId,
                    ClaimType = claimType,
                    ClaimValue = claimValue,
                    UtilityId = utilityid,
                    Description = description
                };

                _dbContext.AspNetRoleClaims.Add(roleClaim);
                _dbContext.SaveChanges();
            }
            catch (Exception ex)
            {
                throw new IdentityNotMappedException(ex.Message, ex);
            }
        }

        public IList<Claim> GetUserClaims(string userId)
        {
            return _userManager.GetClaims(userId);
        }

        public IdentityResult RemoveUserClaim(string userId, string claimType)
        {
            _userManager.UserValidator = new UserValidator<ApplicationUser>(_userManager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };

            var claim = _userManager.GetClaims(userId).FirstOrDefault(t => t.Type == claimType);
            if (claim == null) return IdentityResult.Success;

            return _userManager.RemoveClaim(userId, claim);
        }

        public void DeleteRole(string id)
        {
            var language = new LanguageCodeLookup();
            var aspNetRoles = _dbContext.Roles.FirstOrDefault(r => r.Id == id);

            if (aspNetRoles == null)
                throw new Exception(language.RoleDoesNotExist);
            if (aspNetRoles.Name == "Utility Administrator" ||
                aspNetRoles.Name == "Content Manager" ||
                aspNetRoles.Name == "System Administrator" ||
                aspNetRoles.Name == "Customer Accounts Manager")
                throw new Exception(language.CannotDeleteDefaultRoles);
            if (aspNetRoles.Users.Count > 0)
                throw new Exception(language.CannotDeleteRolesWithUsers);
            _dbContext.Roles.Remove(aspNetRoles);
            _dbContext.SaveChanges();
        }

        public IdentityRole GetRole(string id)
        {
            return _dbContext.Roles.FirstOrDefault(r => r.Id == id);
        }
    }

自定义声明授权属性

public class ClaimsAuthorizeAttribute : AuthorizeAttribute
    {
        private readonly string _claimType;
        public ClaimsAuthorizeAttribute(string type)
        {
            _claimType = type;
        }
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var user = (ClaimsPrincipal)HttpContext.Current.User;

            if (user.HasClaim(_claimType, "True"))
            {
                base.OnAuthorization(filterContext);
            }
            else
            {
                HandleUnauthorizedRequest(filterContext, _claimType + " Not Allowed ");
            }
        }

        protected void HandleUnauthorizedRequest(AuthorizationContext filterContext, string message)
        {
            filterContext.Result = new RedirectToRouteResult(
                                       new RouteValueDictionary
                                   {
                                       { "action", "ClaimNotAuthorized" },
                                       { "controller", "Home" },
                                       {"errorMessage", message }
                                   });
        }

        public static bool AuthorizedFor(string claimType)
        {
            var user = (ClaimsPrincipal)HttpContext.Current.User;
            return user.HasClaim(claimType, "True");
        }
    }

声明使用

[ClaimsAuthorize(ClaimsData.EditCustomer)]
public ActionResult Index(string customerNo = "", int filterID = 0, int filterStatusID = 0)

查看用法剃刀

public static bool AuthorizedFor(this HtmlHelper htmlHelper, string claimType)
    {
        if (!string.IsNullOrEmpty(claimType))
        {
            var user = (ClaimsPrincipal)System.Web.HttpContext.Current.User;
            return user.HasClaim(claimType, "True");
        }
        return false;
    }

如果传递了声明,则呈现HTML字符串

public static MvcHtmlString RenderToastrHiddenInputs(this HtmlHelper htmlHelper, object success, object info, object warning, object error, string claimType)
    {
        if (AuthorizedFor(htmlHelper, claimType))
        {
            var html = string.Format(@"
                <input type='hidden' id='success' value='{0}' />
                <input type='hidden' id='info' value='{1}' />
                <input type='hidden' id='warning' value='{2}' />
                <input type='hidden' id='error' value='{3}' />", success, info, warning, error);

            return new MvcHtmlString(html);
        }

        return null;
    }

希望这一切都有道理:)