我读了一篇关于使用全局过滤器default all MVC Controller Actions到白名单'认证实践&决定尝试一下。
症状:
我做了一个快速测试&控制器操作被正确拒绝,但是......
结果是404 NOT FOUND ......这是有道理的。但是,重定向失败。结果,浏览器只显示一个空的,没有样式的页面。显然,用户永远不会知道它是 404 NOT FOUND ,除非他们足够聪明地查看控制台......这很糟糕。
更新
所有这些代码在这些更改之前都有效。添加FILTER会导致这些症状。
以下是我为进行测试所做的更改...我错过了什么?
MY TEST-CODE看起来像:
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 CONFIG看起来像:
当然,以前所有这些都是在web.config中连接正确运行的。事实上,这确实在测试条件之前运行。
<!-- 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>
答案 0 :(得分:0)
使用ErrorController
属性为[AllowAnonymous]
添加注释。基本上,通过将全局过滤器注册为:
// FORCE: Authorize on all actions (by default)
filters.Add(new AuthorizeAttribute());
您强制用户在登录时看到错误。如果您仍想这样做,则必须跳过此ErrorController
此过滤器(AllowAnonymousAttribute
为您执行此操作。 )
现在回到你的web.config,你不需要在那里添加那个部分。您可以在“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>
答案 1 :(得分:0)
而不是httpErrors
在网络配置中的customErrors
下使用System.Web
元素:
<system.web>
<customErrors mode="On">
<error statusCode="500"
redirect="~/Error/Index" />
<error statusCode="404"
redirect="~/Error/Index" />
</customErrors>
</system.web>
此处错误是控制器名称,索引是操作。