使用AuthorizeAttribute使ErrorsController不可访问
本文关键字:访问 ErrorsController AuthorizeAttribute 使用 | 更新日期: 2023-09-27 18:10:22
我读过一篇关于使用全局过滤器将所有MVC控制器动作默认为"白名单"认证实践的文章& &;决定试一试。
症状:
我做了一个快速测试& &;控制器动作被正确拒绝,但是…
- 异常不再在全局引发。ASAX"Application_Error"……所以它不能(再)重定向。 ErrorsController动作不再触发…所以用户永远不会被重定向到自定义错误
- 注释掉WEB。下面的配置项只会导致页面显示"错误404.15 -未找到"
结果是404 NOT FOUND…这是有道理的。但是,重定向失败。结果,浏览器只显示一个空的、没有样式的页面。显然,用户永远不会知道它是404 NOT FOUND,除非他们足够精明地查看控制台....
更新:
在这些更改之前,所有这些代码都可以正常工作。添加FILTER会导致这些症状。
下面是我为进行测试所做的更改…我错过什么了吗?
我的测试代码看起来像:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
protected void Application_Error(object sender, EventArgs e)
{
HttpContext httpContext = ((MvcApplication)sender).Context;
Exception unhandledException = Server.GetLastError();
HttpException httpException = GetHttpException(unhandledException);
if (httpException != null)
{
int httpCode = httpException.GetHttpCode();
switch (httpCode)
{
// These should redirect automatically.
case (int)HttpStatusCode.Forbidden:
case (int)HttpStatusCode.NotFound:
case (int)HttpStatusCode.Unauthorized:
return;
default:
httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return;
}
}
}
public class FilterConfig
{
#region <Methods>
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// FORCE: Authorize on all actions (by default)
filters.Add(new AuthorizeAttribute());
}
#endregion
}
// The AUTHORIZE ATTRIBUTE is now defaulted on all actions...so we don't need it here
public class AccountController : BaseController
{
#region <Actions>
[HttpGet]
// The TEST is to see the ERRORS PAGE COME UP so put nothing here
public ActionResult Login(string returnUrl)
{
// The user-call should be redirected to the error page when called...but oddly isn't
}
#endregion
}
[AllowAnonymous]
public class ErrorsController : Controller
{
#region <Actions>
// GET: /Errors/Unexpected
[HttpGet]
[AllowAnonymous]
public ActionResult Unexpected()
{
TraceHandler.TraceIn(TraceLevel.Error);
var unitOfWork = new ApplicationUnitOfWork();
var viewModel = new UnExpectedErrorViewModel(unitOfWork);
Response.StatusCode = (int)viewModel.StatusCode;
Response.TrySkipIisCustomErrors = true;
TraceHandler.TraceOut();
return View(viewModel);
}
// GET: /Errors/Forbidden
[HttpGet]
[AllowAnonymous]
public ActionResult Forbidden()
{
TraceHandler.TraceIn(TraceLevel.Error);
var unitOfWork = new ApplicationUnitOfWork();
var viewModel = new ForbiddenErrorViewModel(unitOfWork);
Response.StatusCode = (int)viewModel.StatusCode;
Response.TrySkipIisCustomErrors = true;
Response.SuppressFormsAuthenticationRedirect = true;
TraceHandler.TraceOut();
return View(viewModel);
}
// GET: /Errors/NotFound
[HttpGet]
[AllowAnonymous]
public ActionResult NotFound()
{
TraceHandler.TraceIn(TraceLevel.Error);
var unitOfWork = new ApplicationUnitOfWork();
var viewModel = new NotFoundErrorViewModel(unitOfWork);
Response.StatusCode = (int)viewModel.StatusCode;
Response.TrySkipIisCustomErrors = true;
TraceHandler.TraceOut();
return View(viewModel);
}
#endregion
}
WEB配置如下:
当然,这一切之前都是通过网络实现的。配置以正确运行。而且,实际上,这确实在测试条件之前运行。
<!-- CUSTOM ERRORS: httpErrors -->
<httpErrors existingResponse="Replace" errorMode="Custom">
<remove statusCode="403" subStatusCode="-1" />
<error statusCode="403" prefixLanguageFilePath="" path="/yourapplication/errors/forbidden" responseMode="ExecuteURL" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/yourapplication/errors/notfound" responseMode="ExecuteURL" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="500" prefixLanguageFilePath="" path="/yourapplication/errors/unexpected" responseMode="ExecuteURL" />
</httpErrors>
在web配置中使用System.Web
下的customErrors
元素代替httpErrors
:
<system.web>
<customErrors mode="On">
<error statusCode="500"
redirect="~/Error/Index" />
<error statusCode="404"
redirect="~/Error/Index" />
</customErrors>
</system.web>
这里Error是控制器名称,Index是动作
用[AllowAnonymous]
属性注释您的ErrorController
。基本上,通过将一个全局过滤器注册为:
// FORCE: Authorize on all actions (by default)
filters.Add(new AuthorizeAttribute());
你强迫你的用户在登录时看到错误。如果你仍然想这样做,那么你必须从这个过滤器中跳过你的ErrorController
(AllowAnonymousAttribute
为你做)
现在回到你的网页。配置,你不需要添加那个部分。你可以在你的'Application_Error'方法中处理状态码,如下所示:
protected void Application_Error()
{
var exception = Server.GetLastError();
var httpException = exception as HttpException;
Response.Clear();
Server.ClearError();
var routeData = new RouteData();
routeData.Values["controller"] = "Error";
routeData.Values["action"] = "General";
routeData.Values["exception"] = exception;
Response.StatusCode = 500;
if (httpException != null)
{
Response.StatusCode = httpException.GetHttpCode();
switch (Response.StatusCode)
{
case 403:
routeData.Values["action"] = "Forbidden";
break;
case 404:
routeData.Values["action"] = "NotFound";
break;
case 500:
routeData.Values["action"] = "UnExpected";
break;
}
}
IController errorsController = new ErrorController();
var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
errorsController.Execute(rc);
}
你可能得到404,因为你的路径似乎是错误的。yourapplication
在这些路径中做什么?
<httpErrors existingResponse="Replace" errorMode="Custom">
<remove statusCode="403" subStatusCode="-1" />
<error statusCode="403" prefixLanguageFilePath="" path="/errors/forbidden" responseMode="ExecuteURL" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/errors/notfound" responseMode="ExecuteURL" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="500" prefixLanguageFilePath="" path="/errors/unexpected" responseMode="ExecuteURL" />
</httpErrors>