【问题标题】:How to make Custom PrincipalPermissionAttribute handle user or role changes如何使自定义 PrincipalPermissionAttribute 处理用户或角色更改
【发布时间】:2013-03-05 10:34:25
【问题描述】:

我编写了一个自定义 PrincipalPermissionAttribute,它使用 AuthenticationService 而不是 Thread.CurrentPrincipal,就像 PrincipalPermissionAttribute 一样。

它按我喜欢的方式工作,但是如果用户注销并重新登录,或者如果用户的角色发生变化,则永远不会再次调用属性代码。我怀疑我没有通知它需要重新检查权限的属性? CreatePermission 方法上设置的断点只命中一次。

属性代码是否只评估一次?该属性当前正在为单击我的视图代码隐藏的按钮装饰一个事件处理程序。

如果我将方法改回使用 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
}

【问题讨论】:

  • 能否请您包含已添加到视图按钮单击处理程序的属性的代码?

标签: c# .net security attributes


【解决方案1】:

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

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

我需要创建自己的实现 IPermission 的类并将我的逻辑移到 Demand 方法中。或者(更简单的选项)将我的服务中的 Principal 分配给 Thread.CurrentPrincipal 并使用开箱即用的 PrincipalPermissionAttribute。

【讨论】:

  • 请如果您创建它,请提供代码,因为我有类似的情况,但我需要创建更多粒度级别(Permission-Role-User)并且我需要使 PrincipalPermissionAttribute 来检查权限而不是角色,所以如果您有任何线索将不胜感激
  • 我也有同样的问题,请你看看这个;stackoverflow.com/questions/45770217/…
猜你喜欢
  • 1970-01-01
  • 2011-01-30
  • 2017-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
相关资源
最近更新 更多