クラスをオーバーライドして、カスタム承認を実行します
[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のデフォルトのエラーページが表示されます。ここに何が欠けているのでしょうか。
Max B以外のちょっとしたヒント/メモ:答え:
カスタムエラーを使用している場合は、ErrorsController
とUnAuthorizeActionResultを作成し、次の手順を実行します。
<error statusCode="403" redirect="/Errors/UnAuthorize" />
このようにして、コントローラーで追加情報を追加したり、他のアクションを実行したりできます。次に例を示します。
このようにして、何が起こっているかをさらに制御できます。
これは非常に古い質問ですが、同じ問題を抱えている可能性のある人のために投稿しています。私と同じように、同じ問題を抱えて解決しました。 web.configのcustomErrors要素をトリガーする場合は、以下を試すことができます。
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
throw new HttpException(403, "Forbidden");
}
独自のカスタム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);
}
}
}
403 HttpStatusCodeを割り当てる代わりに、表示したいルートをfilterContext.Resultに割り当てました。
または、以下を使用する代わりに、この代替ソリューションを実行できます。
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);
}
Mvcで401(無許可)、403(禁止)、500(内部サーバーエラー)を処理する方法。 ajax /非ajax呼び出しの場合、およびaspxフォーム認証の下で。
キャッチされていないさまざまな例外を異なる方法で処理し、リクエストがajaxであるかどうかに関係なく、異なる反応をするように変更できます。 auth部分により、通常のmvc Webフォームのredirect-to-login-pageをバイパスし、代わりに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 deny users = "?"を削除することもできます。しかし、MVCフィルタリングにヒットしないレガシーaspxページがあるので、users = "?"を拒否したいと思います。