2013-05-10 147 views
1

是否可以绕过控制器上的授权角色检查,但对某个操作强制执行角色检查?我花了一些时间研究这个,我发现的一切都展示了如何实现AllowAnonymousAttribute。我目前正在使用AllowAnonymousAttribute,它对于完全绕过操作的授权非常有用。这不是我想要的。我有一个需要某些角色的控制器。在请求特定操作时,我想跳过控制器级别的角色,只验证用户是否具有在操作中指定的角色。MVC跳过控制器身份验证使用操作

下面是一些代码:

[Authorize(Roles="Administrator")] 
public class MembersController : ViewApiController<MemberView> 
{ 
    // a list of actions.... 

    [Authorize(Roles="ApiUser")]   
    [HttpPost] 
    public void AutoPayPost([FromBody] List<AutoPayModel> autoPayList) 
    { 
     //.... 
    } 
} 

问题是我希望用户只用“ApiUser”的作用,以有机会获得“AutoPayPost”行动。我意识到我可以删除类级授权属性,然后将其添加到我的控制器上的每个操作方法,减去'AutoPayPost'操作。我想避免这种情况,因为我的几个控制器从一个基类继承而来,该基类提供了需要“管理”角色的一长串操作。因此,我将不得不重写每个基本操作,将Authorize属性添加到重写的方法,然后将调用委托给基类。这将工作,但如果我后来决定添加功能的基类,我将不得不记得回到MembersController并重写新的方法,添加属性等...

这将是伟大的,如果最终的结果是这样的:

[Authorize(Roles="Administrator")] 
public class MembersController : ViewApiController<MemberView> 
{ 
    // a list of actions.... 

    [Authorize(Roles="ApiUser", IgnoreControllerRoles=true)]   
    [HttpPost] 
    public void AutoPayPost([FromBody] List<AutoPayModel> autoPayList) 
    { 
     //.... 
    } 
} 
+0

然后建立一个自定义属性? – 2013-05-10 16:26:21

+0

很好。我将如何在属性中实现这个?使用名为“IgnoreControllerRoles”的属性构建自定义属性是非常简单的部分。它将如何工作?我有一个名为'LogonAuthorizeAttribute'的属性,通过一个动作过滤器全局添加到所有控制器中(http://blogs.msdn.com/b/rickandy/archive/2011/05/02/securing-your-asp-net- MVC -3- application.aspx)。我可以检查这个自定义属性,如果它存在做某事。问题是我不知道如何绕过控制器授权,但允许操作授权。 – jwdenny13 2013-05-10 16:53:02

回答

0

如果我理解正确的话,你可以实现自定义ByPassControllerChecksAttribute(它是用于装饰,你要允许“直通”访问方法),然后在您的LogonAuthorizeAttribute检索动作方法由此请求调用,并检查其自定义属性集合是否具有ByPassControllerChecksAttribute的实例。如果是,请运行检查用户是否被允许访问该方法的代码,否则运行检查用户是否被允许访问该控制器的代码。当然,如果只有一种方法,并且名称已知不会更改,那么可以绕过额外的属性并只检查名称,但当然第一种方法要好得多。

编辑
如果您LogonAuthorizeAttribute从AuthorizeAttribute继承,那么你可以重写AuthorizeCore方法返回boolean(真正意义上的用户被授权,否则为false)。在这种方法中,你可以沿着以下伪的东西:

if(CheckIfMethodHasByPassAttribute()){ 
    return CheckIfUserIsAllowedToRunThisMethod(); 
} 
return CheckIfUserIsAllowedToRunThisController(); 

的方法CheckIfUserIsAllowedToRunThisMethod会有任何检查你需要做的,以确定是否允许用户运行此方法,而CheckIfUserIsAllowedToRunThisController将有代码检查一个用户是否被允许访问控制器(我认为它已经在你的LogonAuthorizeAttribute中)

+0

我有LogonAuthorizeAttribute,我可以检查ByPassControllerChecksAttribute。我不明白如何仅运行操作或控制器授权。我怎么做?你有代码示例吗? – jwdenny13 2013-05-10 18:49:53

1

做这样的事情,你会检查角色/用户是否在角色中,然后否认他们中的任何一个。

public class ByPassAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     string[] roles = this.Roles.Split(','); 
     string[] users = this.Users.Split(','); 


     foreach (var r in roles) 
     { 
      if (httpContext.User.IsInRole(r.Trim())) 
       return false; 
     } 

     foreach (var u in users) 
     { 
      if (httpContext.User.Identity.Name.Equals(u)) 
       return false; 
     } 

     return base.AuthorizeCore(httpContext); 
    } 
} 

然后德科雷这样你的控制器/动作:

[ByPassAuthorize(Roles = "Admin,test,testint", Users = "Tester")] 
    public ActionResult Edit(int id = 0) 
    { 
     FooModel foomodel = db.FooModels.Find(id); 
     if (foomodel == null) 
     { 
      return HttpNotFound(); 
     } 
     return View(foomodel); 
    } 

希望它能帮助你!

+0

好吧,我会给这个镜头。谢谢! – jwdenny13 2013-05-10 18:50:23

+0

您也可以隐藏操作名称以进行验证,HttpContextBase携带操作名称,因此您可以提供另一个参数来检查操作名称AutoPayPost; – Fals 2013-05-10 19:07:07