如何使Authorize属性返回自定义403错误页面而不是redirect到login页面

[Authorize]属性是很好用的MS发明,我希望它能解决我现在的问题

更具体:

当前客户端未通过身份validation – [Authorize]从安全操作redirect到login页面,login成功后 – 将用户退回,这很好。

但是,当前的客户端已经通过身份validation,但没有授权运行特定的操作 – 我需要的只是显示我的通用403页面。

没有在控制器的内部移动授权逻辑是否可能?

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

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

所以 – 不应该有任何redirect和url应该保持不变,但页面的内容应该被replace为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" }; } } 

并不能得到如何正确地转发到HomeController.Action_403(),所以它显示403。

更新3

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

所以这是如何呈现特定的视图模板的答案…但仍然不知道如何运行另一个控制器 – 无论如何,这是足够好的解决scheme。

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

如果您需要对授权进行更细粒度的控制,则build议您创buildIActionFilter接口的实现(在属性上,然后将该属性应用于您的方法)。 这将允许您在呼叫到达控制器之前拦截呼叫,并调用控制器方法之前提供备用操作。

这是通过在IActionFilter接口上实现OnActionExecuting方法来实现的。 如果您的逻辑确定您不应该对控制器进行调用,并且您想要提供一个ActionResult来处理,那么您将在传递给该方法的ActionExecutingContext实例上设置Result属性 。 通过这样做, ActionResult被处理,而不是去控制器方法得到一个ActionResult

如果你想返回一个403错误代码,那么你不能使用ContentResult类。 您将不得不创build自己的派生自ActionResult的类并重写ExecuteResult方法,以将HttpResponseBase上的StatusCode属性设置为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类来接受一个构造函数,它将接受你想要返回的状态码,但是这个概念保持不变。

我会做什么是子类AuthorizeAttribute,并重写它的HandleUnauthorizedRequest返回HTTP状态代码403,如果用户通过身份validation。 然后,我会添加一个system.webServer \ httpErrors部分到我的Web.Config来replace默认的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>