2

PrincipalPermissionAttribute のように、Thread.CurrentPrincipal の代わりに AuthenticationService を使用するカスタム PrincipalPermissionAttribute を作成しました。

思い通りに動作しますが、ユーザーがログアウトして再度ログインした場合、またはユーザーの役割が変更された場合、属性コードが 2 回呼び出されることはありません。許可を再確認する必要がある属性に通知していないのではないでしょうか? 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
}
4

1 に答える 1

1

わかりました、私はそれがどのように機能するかを理解しました。CreatePermission は、実際には 1 回だけ呼び出されます。返される IPermission は、ユーザーが必要なロールにあるかどうかをチェックするクラスです。

ユーザー A に対して無制限の許可を返していたため、ユーザー B は役割に関係なく同じアクセス権を取得しました。

IPermission を実装する独自のクラスを作成し、ロジックを Demand メソッドに移動する必要があります。または (より簡単なオプション)、サービスのプリンシパルを Thread.CurrentPrincipal に割り当て、すぐに使用できる PrincipalPermissionAttribute を使用します。

于 2013-03-05T02:34:25.373 に答える