如何在mvc中處理401(未授權),403(禁止)和500(內部服務器錯誤)。對於ajax/non-ajax調用和在aspx表單認證下。
它可以被修改以不同的方式處理各種未捕獲的異常,並對請求是否是ajax做出不同的反應。 auth部分允許它繞過任何常規的mvc web表單重定向到登錄頁面,而是返回401未授權的 - 那麼你的客戶端js框架可以更容易地對http狀態401/403做出反應。
// FilterConfig.cs:
filters.Add(new ApplicationAuthorizeAttribute());
filters.Add(new ApplicationHandleErrorAttribute());
public class ApplicationAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// Note: To reach here, a Web.config path-specific rule 'allow users="?"' is needed (otherwise it redirects to login)
var httpContext = filterContext.HttpContext;
var request = httpContext.Request;
var response = httpContext.Response;
if (request.IsAjaxRequest())
{
response.SuppressFormsAuthenticationRedirect = true;
response.TrySkipIisCustomErrors = true;
}
filterContext.Result = new HttpUnauthorizedResult();
}
}
public class ApplicationHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
var exception = context.Exception is AggregateException
? ((AggregateException)context.Exception).InnerExceptions.First()
: context.Exception;
var request = context.HttpContext.Request;
var response = context.HttpContext.Response;
var isAjax = request.IsAjaxRequest();
if (exception is MyCustomPermissionDeniedException)
{
filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
response.TrySkipIisCustomErrors = isAjax;
filterContext.ExceptionHandled = true;
return;
}
#if DEBUG
if (!isAjax)
{
// Show default aspx yellow error page for developers
return;
}
#endif
var requestUri = request.Url == null ? "" : request.Url.AbsoluteUri;
MyCustomerLogger.Log(exception, requestUri);
response.Clear();
response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
#if DEBUG
var errorMessage = exception.Message;
#else
var errorMessage = "An error occurred, please try again or contact the administrator.";
#endif
response.Write(isAjax
? JsonConvert.SerializeObject(new {Message = errorMessage})
: errorMessage);
response.End();
response.TrySkipIisCustomErrors = true;
context.ExceptionHandled = true;
}
}
Web.config文件:
<system.webServer>
<authentication mode="Forms">
<forms name=".MYAUTHCOOKIE" protection="All" loginUrl="/Account/Login" timeout="18000" slidingExpiration="true" enableCrossAppRedirects="false" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
</system.webServer>
<!-- ajax api security done via ApplicationAuthorizeAttribute -->
<location path="api">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
用於Web服務的API請求其他路線:(把上面的正MVC路線)
// This route has special ajax authentication handling (no redirect to login page)
routes.MapRoute(
name: "DefaultApi",
url: "api/{controller}/{action}/{id}",
defaults: new { id = UrlParameter.Optional }
);
示例客戶端代碼的jQuery來處理錯誤:
$.ajaxSetup({
complete: function onRequestCompleted(xhr, textStatus) {
if (xhr.readyState == 4 && xhr.status == 401) {
// Not needed with smart status: && xhr.responseText.substring(0, 150).indexOf("<title>Log in") != -1
//location.href = "/Account/Login";
alert("Your session has timed out.");
}
}
});
或者,你可以讓所有的認證都通過ApplicationHandleErrorAttribute,並且擺脫那個web.config拒絕用戶=「?」。但我有一個遺留的aspx頁面,它不會打擊mvc過濾,所以我想要拒絕用戶=「?」。
其實我在做同樣的事情,共享是控制器和未經授權的行爲,但我仍然收到相同的默認HTTP 403頁面錯誤,而不是我定義的頁面 –
非常有幫助的鏈接http://stackoverflow.com/questions/2504923/how -to-redirect-authorize-to-loginurl-only-when-roles-are-not-used –
@SaboorAwan。我也嘗試過,沒有運氣。控制器方法永遠不會被調用。您是否通過此答案或您發佈的鏈接解決了問題? – Marco