我想根据ApplicationUser
s ApplicationRole
来授权RoleClaim
。我想这样实现:
public class RoleClaimAuthorizeAttribute : AuthorizeAttribute
{
public RoleClaim RoleClaim { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
foreach (ApplicationRole role in Roles)
{
if ((RoleClaim & role.Claims) > 0)
{
return true;
}
}
return false;
}
}
然后我可以像这样装饰控制器动作:
[RoleClaimAuthorize(RoleClaim =
RoleClaim.CanCreateRoles |
RoleClaim.CanReadRoles |
RoleClaim.CanDeleteRoles |
RoleClaim.CanUpdateRoles
)]
//
// GET: /Roles/
public ActionResult Index()
{
return View(_roleManager.Roles);
}
我遇到的问题是我可以找到从我的自定义authorize属性到达ApplicationUser
ApplicationRole
的任何方法返回ApplicationRole.Name
的字符串数组而不是数组ApplicationRole
所以我无法前往ApplicationRole.Claims
。我也使用Unity代替Owin来处理ApplicationRoleManager
,因此我无法通过ApplicationRoleManager
请求HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>()
。
那么如何才能为当前用户获取ApplicationRole
个对象的集合,从而ApplicationRole.Claims
?
或者,如果它是一个更合适的解决方案,我如何在ApplicationUser
中存储当前ApplicationRole
的{{1}} s'RoleClaim
的字符串数组,就像如何角色存储?我知道我的授权属性不能像这种情况所描述的那样工作,但这是我可以使用的情况。
HttpContext
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser<Guid, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public override Guid Id { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, Guid> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, Guid> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
}
public class ApplicationRole : IdentityRole<Guid, ApplicationUserRole>
{
public ApplicationRole() : base()
{
this.Id = Guid.NewGuid();
}
public ApplicationRole(string name)
: this()
{
this.Name = name;
}
public ApplicationRole(string name, params string[] claims)
: this(name)
{
Claims = (RoleClaim)Enum.Parse(typeof(RoleClaim), String.Join(",", claims));
}
public RoleClaim Claims { get; set; }
}
[Flags]
public enum RoleClaim : int
{
CanCreateUsers = 1,
CanReadUsers = 2,
CanUpdateUsers = 4,
CanDeleteUsers = 8,
CanCreateRoles = 16,
CanReadRoles = 32,
CanUpdateRoles = 64,
CanDeleteRoles = 128,
CanCreateTests = 256,
CanReadTests = 512,
CanUpdateTests = 1024,
CanDeleteTests = 2048
}
答案 0 :(得分:1)
如果您在Unity中注册了角色管理器,只需调用以下方法即可在任何地方检索,包括您的自定义属性:
var roleManager = DependencyResolver.Current.GetService<ApplicationRoleManager>();
或者,如果您不想直接使用解析器,则可以使用Unity的属性注入功能,以便Unity自动在自定义属性中注入角色管理器,在解释here时。然后调用roleManager.FindByNameAsync()
方法来检索角色对象。
但不推荐这种方法,因为在每次调用中,您的代码都会访问数据库以检索声明。最好在用户登录时在ClaimsIdentity
中存储用户的声明,然后在属性中检索它们,如下所示:
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
private readonly ApplicationRoleManager _roleManager;
public ApplicationSignInManager(ApplicationUserManager userManager,
IAuthenticationManager authenticationManager,
ApplicationRoleManager rolemanager)
: base(userManager, authenticationManager)
{
//inject the role manager to the sign in manager
_roleManager=rolemanager;
}
public override async Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
var ident= await user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
// add your custom claims here
var userRoles=user.Roles.Select(r=>r.RoleId);
ident.AddClaims(_roleManager.Roles.Where(r => userRoles.Any(ur => ur == r.Id))
.Select(r=>r.Claims).ToList()
.Select(c => new Claim("RoleClaims", c.ToString())));
return ident;
}
}
现在RoleClaims
在用户登录时添加为声明。您可以在属性中检索它们,如下所示:
public class RoleClaimAuthorizeAttribute : AuthorizeAttribute
{
public RoleClaim RoleClaim { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
foreach (var claims in GetClaims(httpContext.User.Identity as ClaimsIdentity))
{
if ((RoleClaim & claims) > 0)
{
return true;
}
}
return false;
}
private IEnumerable<RoleClaim> GetClaims(ClaimsIdentity ident)
{
return ident==null
? Enumerable.Empty<RoleClaim>()
: ident.Claims.Where(c=>c.Type=="RoleClaims")
.Select(c=>(RoleClaim)Enum.Parse(typeof(RoleClaim), c.Value));
}
}