首页> C#>如何使授权属性返回自定义403错误页面,而不是重定向到登录页面

[Authorize]属性是MS发明的好帮手,我希望它可以解决我现在遇到的问题

更加具体:

当当前客户端未通过身份验证时-[Authorize]从安全操作重定向到登录页面,并且登录成功后-将用户带回,这很好。

但是,如果当前的客户端已经通过身份验证但未获得运行特定操作的权限-我需要的只是显示我的一般403页面。

是否可以在控制器的内部不移动授权逻辑?

更新:我需要的行为在语义上应与此草图相同:

public ActionResult DoWork()
{
    if (!NotAuthorized())
    {
        // this should be not redirect, but forwarding 
        return RedirectToAction("403");         
    }

    return View();
}

因此-不应有任何重定向,并且url应该保持不变,但该页面的内容应替换为403-page

更新2:我以这种方式实现了草图:

[HandleError]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    [CustomActionFilter]
    public ActionResult About()
    {
        return View();
    }

    public ActionResult Error_403()
    {
        return Content("403");
    }
}

public class CustomActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.Result = new ContentResult { Content = "403" };
    }
}

而且无法获取如何正确地将执行转发到HomeController.Action_403(),因此它显示403。

更新3:

filterContext.Result = new ViewResult() { ViewName = "Error_403" };

所以这是关于如何呈现特定视图模板的答案...但是仍然不知道如何运行另一个控制器-无论如何,这已经足够了。

zerkms asked 2020-01-23T18:52:45Z
2个解决方案
49 votes

我要做的是子类AuthorizeAttribute,并重写其HandleUnauthorizedRequest以在用户通过身份验证时返回HTTP状态代码403。 然后,我将system.webServer \ httpErrors部分添加到Web.Config中,以用我的自定义页面替换默认的403(这最后一部分需要IIS 7+)。 就是这样:

public class MyAuthorizeAttribute : AuthorizeAttribute {
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            filterContext.Result = new HttpStatusCodeResult(403);
        else
            filterContext.Result = new HttpUnauthorizedResult();
    } 
}

<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="403" />
      <error statusCode="403" responseMode="ExecuteURL" path="/Error/MyCustom403page" />
    </httpErrors>
  </system.webServer>
</configuration>
zvolkov answered 2020-01-23T18:53:39Z
35 votes

您应该能够创建自己的派生自Http403Result的类,并重写Http403Result方法以提供所需的授权机制,以便可以通过使用属性来应用自定义授权代码,而不是将其移入控制器。

如果需要对授权进行更细粒度的控制,则建议您创建Http403Result536接口的实现(在属性上,然后将该属性应用于您的方法)。 这样一来,您就可以截获到控制器之前的调用,并在调用控制器方法之前提供其他操作。

这是通过在Http403Result接口上实现Http403Result方法来实现的。 如果您的逻辑确定根本不应该对控制器进行调用,而您想提供要处理的Http403Result,则可以在传递给方法的Http403Result实例上设置Http403Result属性。 这样,将处理ActionResult而不是转到控制器方法来获取ActionResult

如果要返回403错误代码,则不能使用Http403Result类。 您将必须创建一个派生自ActionResult的类,并重写Http403Result方法以将Http403ResultHttp403Result属性设置为403,如下所示:

internal class Http403Result : ActionResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        // Set the response code to 403.
        context.HttpContext.Response.StatusCode = 403;
    }
}

public class CustomActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.Result = new Http403Result();
    }
}

当然,您可以将Http403Result类推广为一个构造函数,该构造函数将接受您要返回的状态代码,但是概念仍然相同。

casperOne answered 2020-01-23T18:53:18Z
translate from https://stackoverflow.com:/questions/2578756/how-to-make-authorize-attribute-return-custom-403-error-page-instead-of-redirect