如何使Authorize属性返回自定义403错误页面而不是重定向到登录页面

zer*_*kms 51 .net c# security asp.net-mvc authorization

[Authorize] 属性很好,方便的MS发明,我希望它能解决我现在遇到的问题

更具体:

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

但是当当前客户端已经过身份验证但没有被授权运行特定操作时 - 我只需要显示我的常规403页面.

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

更新:我需要的行为应该在语义上等于这个草图:

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

    return View();
}
Run Code Online (Sandbox Code Playgroud)

所以 - 应该没有任何重定向和url应该保持不变,但页面的内容应该替换为403页

更新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" };
    }
}
Run Code Online (Sandbox Code Playgroud)

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

更新3:

filterContext.Result = new ViewResult() { ViewName = "Error_403" };
Run Code Online (Sandbox Code Playgroud)

所以这是一个关于如何渲染特定视图模板的答案...但仍然不知道如何运行另一个控制器 - 无论如何,这是足够好的解决方案.

zvo*_*kov 49

我要做的是继承AuthorizeAttribute并覆盖其HandleUnauthorizedRequest以在用户通过身份验证时返回HTTP状态代码403 .然后我会在我的Web.Config中添加一个system.webServer\httpErrors部分,用我的自定义页面替换默认的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>
Run Code Online (Sandbox Code Playgroud)


cas*_*One 35

您应该能够创建自己的类,该类派生自AuthorizeAttribute并覆盖该AuthorizeCore方法以提供所需的授权机制,以便您可以使用属性而不是将其移动到控制器中来应用自定义授权代码.

如果您需要对授权进行更细粒度的控制,那么我建议您创建IActionFilter接口的实现(在属性上,然后将属性应用于您的方法).这将允许您在调用之前拦截调用,并调用控制器方法之前提供备用操作.

这是通过在接口上实现该OnActionExecuting方法来实现的IActionFilter.如果您的逻辑确定您根本不应该对控制器进行调用,并且您想要提供ActionResult要处理的内容,那么您将在传递给该方法的实例上设置该Result属性ActionExecutingContext.通过执行此操作,ActionResult处理而不是转到控制器方法来获取ActionResult.

如果要返回403错误代码,则无法使用ContentResult该类.您将必须创建自己的类,该类派生自ActionResult并覆盖在403 上ExecuteResult设置StatusCode属性的方法HttpResponseBase,如下所示:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以将Http403Result类概括为一个构造函数,该构造函数将接受您想要返回的状态代码,但概念保持不变.