簡體   English   中英

自定義授權(權限)ASP.NET MVC

[英]Custom Authorization (Permissions) ASP.NET MVC

在我的應用程序中,角色具有多個權限。 我希望用戶可以訪問依賴於權限的操作,而不是角色。

所以假設:

  • 管理員有perm1,perm2,perm3,
  • SuperAdmin擁有管理員擁有的所有權限+ perm4和perm5。
  • 此外,還有一些小家伙也有perm1,perm3,perm6,perm7。

我想做以下事情:我想讓那些假設perm3或perm4的人可以訪問動作。 這兩個權限來自兩個不同的角色。 但是除了perm3 Admin有perm1和perm2之外,這個動作也可以由具有perm3的小家伙訪問(不一定是admin或superadmin)。

所以你明白我的意思吧? 我想在ASP.NET MVC 4中實現這一點。所以我想我需要創建自己的AuthorizeAttribute ,我自己的IIdentity並在global.asax中編寫一些方法。 ASP.NET中還有一個成員資格我是否需要觸摸它? 我不知道如何把所有的東西放在一起。 誰能幫我嗎?

public class PermissionAttribute : AuthorizeAttribute
    {
        private readonly IAccountService _accountService;
        private readonly IEnumerable<PermissionEnum> _permissions;

        public PermissionAttribute(params PermissionEnum[] permissions):
            this(DependencyResolver.Current.GetService<IAccountService>())
        {
            _permissions = permissions;
        }

        protected PermissionAttribute(IAccountService accountService)
        {
            _accountService = accountService;
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if(!_permissions.Any(x=>_accountService.HasPermission(filterContext.HttpContext.User.Identity.Name,(int)x)))
                filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
            base.OnAuthorization(filterContext);
        }

    }

基本上你必須創建自己的AuthorizeAttribute,但是使用.NET中的IIdentity。 您在此處描述的是基於聲明的身份驗證和授權系統。

很可能您將不得不從ASP.NET中丟棄成員資格或僅使用其中的一部分。 據我所知,它並沒有考慮到索賠。

在.NET 4.5中,這些人添加了類:ClaimsPrincipal,它實現了IPrincipal接口。 此類可用於實現基於聲明的自定義身份驗證和授權。

因此,當用戶通過身份驗證時,您可以在線程上添加聲明:

var id = new ClaimsIdentity(claims, "Dummy");
var principal = new ClaimsPrincipal(new[] { id });
Thread.CurrentPrincipal = principal;

然后再使用你在Thread.CurrentPrincipal上找到的聲明。

在ASP.NET MVC中,您可以執行以下步驟:

  1. 創建一個對用戶進行身份驗證的委托處理程序。 如果用戶已通過身份驗證,則會將聲明添加到線程主體。 理想情況下,此委托處理程序應盡可能高,以便您可以在執行鏈中的任何位置使用聲明。 還記得使用相同的主體設置HttpContext.Current.User

    公共類AuthHandler:DelegatingHandler {

     protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { //authenticate user //get claims //create principal var newPrincipal = CreatePrincipal(claims); Thread.CurrentPrincipal = newPrincipal; if (HttpContext.Current != null) HttpContext.Current.User = newPrincipal; return await base.SendAsync(request, cancellationToken); } 

    }

  2. 創建一個過濾器,根據添加到Thread Principal的聲明進行授權。 在這里,您可以執行諸如將當前路線與聲明中的信息進行比較之類的操作。

所以我認為你說的是​​:只有當用戶有perm1,perm2時才能訪問ActionA,當用戶有perm1和perm3時,類似的ActionB是可訪問的

我給出的代碼是為了說明,我沒有編譯它。 但是會給你我所說的方法的圖片

步驟1:您可以繼續創建使用Flags屬性歸屬的權限枚舉

第2步:根據存儲在數據存儲中的用戶權限向當前主體添加聲明。

第3步:調用Action時,授權訪問聲明

[Flags]
    enum PermType
    {
        None = 0x0,
        Perm1 = 0x1,
        perm2 = 0x2,
        perm3 = 0x4,
        perm4 = 0x8,
        perm5 = 0x10 
    }

將聲明添加到CurrentPrincipal

var currentPrincipal = ClaimsPrincipal.Current;
var cms = currentPrincipal.Claims;
var permissions = PermType.Perm1 | PermType.perm2;
var claims = cms.ToList();
claims.Add(new Claim("Action1", permissions.ToString()));
claims.Add(new Claim("Action2", permissions.ToString()));
claims.Add(new Claim("Action3", permissions.ToString()));
System.Threading.Thread.CurrentPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims));

檢查用戶是否可以訪問特定操作

public bool CanAccessThisAction(string acionName,PermType requiredPerms)
{
    var claim = principal.Claims.FirstOrDefault(c => c.Type == acionName);
    if (customPermissionClaim != null)
    {
        //check if required permission is present in claims for this user
        //return true/false
    }
    return false;
}

在行動

public ActionResult TestAction(string id)
{
    if(CanAccessThisAction("TestAction",PermType.Perm1|PermType.perm3|PermType.perm5))
    {
        //do your work here
    }
    else
    {
        //redirect user to some other page which says user is not authorized
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM