我编写了一个自定义PrincipalPermissionAttribute,它使用AuthenticationService而不是Thread.CurrentPrincipal作为PrincipalPermissionAttribute。
它可以按我喜欢的方式工作,但如果用户注销并重新登录,或者用户的角色要更改,则属性代码永远不会再次调用。我怀疑我没有通知重新检查权限所需的属性?在CreatePermission方法上设置的断点只能命中一次。
属性代码是否只评估过一次?该属性当前正在为我的View的代码隐藏点按钮点击一个事件处理程序。
如果我改回我的方法以使用PrincipalPermissionAttribute,那么它确实可以正常工作,以没有正确角色的用户身份退出并重新登录会抛出我期望的SecurityException。我是否错过了覆盖房产?
[Serializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class RolePermissionAttribute : CodeAccessSecurityAttribute
{
private readonly PrincipalPermission _revoke = new PrincipalPermission(PermissionState.None);
private readonly PrincipalPermission _allow = new PrincipalPermission(PermissionState.Unrestricted);
private IList<string> _roles;
private readonly IAuthenticationService _authorisationService;
public RolePermissionAttribute(SecurityAction action)
: this(action, ServiceLocator.Current.GetInstance<IAuthenticationService>())
{
}
public RolePermissionAttribute(SecurityAction action, IAuthenticationService authorisationService)
: base(action)
{
_authorisationService = authorisationService;
}
public string Roles { get; set; }
public bool Authenticated { get; set; }
public override IPermission CreatePermission()
{
_roles = (this.Roles ?? string.Empty).Split(',', ';')
.Select(s => s.Trim())
.Where(s => s.Length > 0)
.Distinct()
.ToList();
bool result = false;
if (_authorisationService != null)
{
var principal = _authorisationService.ClientSecurityPrincipal;
if (principal == null)
{
throw new SecurityException("Access Denied. You are not logged in");
}
// If Authenticated is enforced then revoke if user is not authenticated
if (Authenticated && !_authorisationService.IsAuthenticated)
{
throw new SecurityException("Access Denied. You are not authenticated");
}
// Allow if the principal is in any of the roles
result = _roles.Any(principal.IsInRole);
if (!result)
{
throw new SecurityException("Access Denied. You are not in an allowed Role");
}
}
return result ? _allow : _revoke;
}
}
}
这是带有属性
的方法[RolePermission(SecurityAction.Demand, Authenticated = true, Roles = "Admin")]
private void barButtonItemConfig_ItemClick(object sender, ItemClickEventArgs e)
{
// Do stuff
}
答案 0 :(得分:1)
好的,我已经弄清楚它是如何工作的。 CreatePermission实际上只被调用一次。返回的IPermission是检查用户是否处于所需角色的类。
因为我返回了对用户A的无限制允许,所以用户B无论其角色如何都获得相同的访问权限。
我需要创建自己的类来实现IPermission并将我的逻辑移动到Demand方法中。或者(更容易的选择)将Principal从我的服务分配给Thread.CurrentPrincipal并使用现成的PrincipalPermissionAttribute。