【问题标题】:How do I invalidate claims using ASP.NET Identity?如何使用 ASP.NET Identity 使声明无效?
【发布时间】:2014-03-11 13:44:26
【问题描述】:

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

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

声明默认存储在身份验证 cookie 中,这很酷。但是,当有关用户的信息发生更改(即从角色中添加或删除)时,这会带来问题。

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

有没有办法在 ASP.NET Identity 中使用声明并知道它们何时不再有效?该框架是否提供任何选项来解决这个问题?

【问题讨论】:

  • 您是否担心一起撤销访问权限(身份验证)或对特定区域的访问权限(通常是角色/授权)?
  • 我真的只关心访问(授权)。如果可以使声明无效(也许是某种安全令牌更改?),我会喜欢它。例如,如果将用户添加到某个“管理员”角色,我希望用户能够访问需要该角色的资源,而无需重新进行身份验证。我看到 Identity 框架有一个 ClaimStore 接口,我正在避免使用(包括默认实体框架实现似乎使用的声明数据库表)。
  • 我遇到了同样的问题并意识到如果我重新登录用户,声明会更新,请参阅this answer

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


【解决方案1】:

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

What is the SecurityStamp used for?

【讨论】:

    【解决方案2】:

    我最近在一个项目中实现了基于声明的功能集。我发现 Identity 不提供物理更新用户声明的机制。 MS 构建这个的方式似乎你必须从用户那里删除一个声明,这样当自定义授权属性被点击时,它会看到用户没有声明,因此不会通过。

    我必须构建它的方式是使用视图和控制器实现一个单独的基本声明实用程序来管理我的自定义声明。例如,当我创建一个新用户时,我将各种声明分配给该用户。我还有一个扩展或自定义的身份管理器类,用于管理我的用户声明、密码、帐户锁定、添加新角色和删除角色。

    对于视图,我创建了自定义 HTML.Helper 扩展方法来帮助验证用户是否可以访问。

    下面是一些代码示例。

    身份管理器类

    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;
        }
    

    希望这一切都有意义:)

    【讨论】:

      猜你喜欢
      • 2016-02-18
      • 1970-01-01
      • 1970-01-01
      • 2014-08-26
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多