如何使Custom PrincipalPermissionAttribute处理用户或角色更改

时间:2013-03-04 04:27:53

标签: c# .net security attributes

我编写了一个自定义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
}

1 个答案:

答案 0 :(得分:1)

好的,我已经弄清楚它是如何工作的。 CreatePermission实际上只被调用一次。返回的IPermission是检查用户是否处于所需角色的类。

因为我返回了对用户A的无限制允许,所以用户B无论其角色如何都获得相同的访问权限。

我需要创建自己的类来实现IPermission并将我的逻辑移动到Demand方法中。或者(更容易的选择)将Principal从我的服务分配给Thread.CurrentPrincipal并使用现成的PrincipalPermissionAttribute。