我近期實施了一個基於聲明的功能在project.I設置發現身份不提供實際更新用戶聲明的機制。 MS建立它的方式好像你必須從用戶中刪除一個聲明,所以當Custom Authorize屬性被擊中時,它會看到用戶沒有聲明,因此不會通過。我必須構建它的方式是實現一個單獨的基礎聲明實用程序與視圖和控制器來管理我的自定義聲明,例如當我創建一個新用戶時,我爲用戶分配了各種聲明。我還有一個擴展的或自定義的Identity Manager類,用於管理我的用戶聲明,密碼,鎖定添加新角色和刪除角色的帳戶。 在我的看法一面我創建了一個自定義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;
}
希望這一切有意義:)
您是否擔心撤銷訪問一起(認證)還是訪問特定區域(通常是角色/授權)? –
我真的只關心訪問(授權)。如果索賠可能會失效(可能是安全令牌更改的種類?),我想要它。例如,如果用戶被添加到某個「管理員」角色,我希望用戶能夠訪問需要該角色的資源,而無需重新進行身份驗證。我看到Identity框架有一個'ClaimStore'接口,我避免了這個接口(包括默認的實體框架實現似乎使用的聲明數據庫表)。 –