MVC跳过控制器身份验证使用操作

时间:2013-05-10 16:03:10

标签: asp.net-mvc authorization

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

以下是一些代码:

[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”操作。我意识到我可以删除类级别authorize属性,然后将其添加到我的控制器上的每个操作方法,减去'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)
    {
        //....
    }
}

2 个答案:

答案 0 :(得分: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);
    }

希望对你有所帮助!

答案 1 :(得分:0)

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

修改
如果您的LogonAuthorizeAttribute继承自AuthorizeAttribute,那么您可以覆盖返回布尔值的AuthorizeCore方法(true表示用户已获得授权,否则为false)。在这种方法中,您可以使用以下伪代码:

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

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