我会覆盖该类以执行自定义授权
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
现在在web.config中我配置了403错误页面
<customErrors defaultRedirect="/Shared/Error" mode="On">
<error statusCode="403" redirect="/Shared/UnAuthorize" />
</customErrors>
但浏览器仍显示403的默认错误页面, 我在这里缺少什么,任何想法
答案 0 :(得分:11)
除了Max B之外,只是一个小提示/注释:
当我使用自定义错误时,我会创建一个ErrorsController
和一个UnAuthorize ActionResult并执行以下操作:
<error statusCode="403" redirect="/Errors/UnAuthorize" />
这样我可以在控制器中添加额外信息或执行其他操作,例如:
通过这种方式,您可以更好地控制正在发生的事情。
答案 1 :(得分:10)
我知道这是一个非常古老的问题,但我会为可能遇到同样问题的人发帖。像我一样,我有同样的问题并解决了它。如果要在web.config中触发customErrors元素,可以尝试以下。
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
throw new HttpException(403, "Forbidden");
}
答案 2 :(得分:6)
我遇到了与编写自己的自定义AuthorizeAttribute时完全相同的问题。当我在web.config中添加“customErrors”标记时,403的自定义错误页面将不会显示。 这就是我解决问题的方法:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Error",
action = "Unauthorised"
})
);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
将我想要显示的路由分配给filterContext.Result,而不是分配403 HttpStatusCode。
答案 3 :(得分:3)
或者你可以做这个替代解决方案,而不是使用:
filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403);
您可以将其更改为:
if (filterContext.HttpContext.Request.IsAuthenticated)
{
throw new UnauthorizedAccessException();
}
在Controller / BaseController中覆盖方法OnException(ExceptionContext filterContext)
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled)
{
return;
}
if (filterContext.Exception.GetType() == typeof(UnauthorizedAccessException))
{
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Error/NotAuthorized.cshtml"
};
filterContext.ExceptionHandled = true;
return;
}
base.OnException(filterContext);
}
答案 4 :(得分:0)
如何在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.");
}
}
});
或者,你可以让所有auth通过ApplicationHandleErrorAttribute,并摆脱那个web.config deny users =“?”。但我有一个遗留的aspx页面没有点击mvc过滤所以我想要拒绝用户=“?”。
答案 5 :(得分:0)
1-创建一个名为 LoggedOrAuthorizedAttribute
的类
public class LoggedOrAuthorizedAttribute: AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
CheckIfUserIsAuthenticated(filterContext);
}
private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext)
{
// If Result is null, we're OK: the user is authenticated and authorized.
if (filterContext.Result == null)
return;
// If here, you're getting an HTTP 401 status code. In particular,
// filterContext.Result is of HttpUnauthorizedResult type. Check Ajax here.
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectResult("/Error/Error401");
}
}
}
2-将您创建的属性添加到您的操作顶部
[LoggedOrAuthorizedAttribute(Roles = "Admin")]
public ActionResult Index()
{
return View();
}
[LoggedOrAuthorizedAttribute(Roles = "User")]
public ActionResult IndexUser()
{
return View();
}
答案 6 :(得分:-1)
对我而言,似乎HttpStatusCodeResult(403)在错误的if分支中。在我看来,代码应如下所示:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403);
}
}
}