问题
I created an ASP.NET MVC application that uses integrated Windows Authentication. The following authorization logic was implemented:
Try to get account credentials from active directory through NTLM.
- If credentials are received and the Windows account has required permissions then perform requested action.
- In otherwise go to clause 2.
Display the Windows authentication dialog, so a user can provide another credentials:
- If another credentials are received and the user has required permissions then perform requested action.
- If another credentials are not received or the account permissions are less then it requires, then repeat clause 2.
- If authentication dialog is cancelled then display 401 error message.
Then I have added custom error pages for the application, using VictorySaber's solution:
protected void Application_EndRequest()
{
int status = Response.StatusCode;
string actionName;
if (status >= 400 && status < 500)
{
switch (status)
{
case 401:
actionName = "Unauthorized";
break;
// Handle another client errors
default:
actionName = "BadRequest";
break;
}
}
else if (status >= 500 && status < 600)
{
switch (status)
{
case 501:
actionName = "NotImplemented";
break;
// Handle another server errors
default:
actionName = "InternalServerError";
break;
}
}
if (!String.IsNullOrEmpty(actionName))
{
Response.Clear();
var rd = new RouteData();
rd.Values["controller"] = "Errors";
rd.Values["action"] = actionName;
IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
}
}
As result my friendly error pages are rendered. But the Windows authentication dialog does not appear. If the 401 HTTP status code occurs it immediately displays 401 error message. The trick with the <httpErrors>
section of web.config file gives same result.
Also, I found proposal to catch the 401.2 HTTP status code that should occur when the dialog is cancelled. But in my case the code never occurs.
How to use user friendly error pages instead of default messages but don't change authentication dialog logic?
I need to implement the following requirements:
- The Windows authentication dialog is appeared only for a user, whose AD account doesn't have required permissions, to allow the user provides another credentials.
- The dialog is appeared while correct credentials are not provided or user doesn't cancel it.
- The custom 401 error page will be displayed only if the user cancels the dialog.
回答1:
One small but important detail was missed. By default the server leaves the response untouched only if the SetStatus
flag is set. So, it is necessary to clearly specifiy what IIS must to do with an existing response when the HTTP status code is an error.
One way is to configure the <httpErrors> element of <system.webServer>
section in the Web.config file. Just set existingResponse
attribute value to PassThrough
, so that the server leaves the response untouched if an existing response exists.
<system.webServer>
<!-- configuration settings -->
<httpErrors errorMode="Custom" existingResponse="PassThrough" />
</system.webServer>
The configuration prevent error page rendering if the sever prompts for a Windows user account credentials. The response will be replaced with the error page after the dialog cancellation.
The same result could be achieved by disabling of IIS custom errors through TrySkipIisCustomErrors property of HttpResponse
. So the
addition the following line to code from the question solves the problem:
Context.Response.TrySkipIisCustomErrors = true;
Note. The second way does not work on my production server for some reason. I think, it requires additional server settings.
来源:https://stackoverflow.com/questions/51304236/custom-401-error-page-for-asp-net-mvc-application