2

是否可以绕过控制器上的授权角色检查,但对操作强制执行角色检查?我花了一些时间研究这个,我发现的所有内容都显示了如何实现 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”操作。我意识到我可以删除类级别的授权属性,然后将其添加到我的控制器上的每个操作方法中,减去“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)
    {
        //....
    }
}
4

2 回答 2

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);
    }

希望对您有所帮助!

于 2013-05-10T18:29:25.613 回答
0

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

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

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

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

于 2013-05-10T18:17:05.787 回答