ASP.NET MVC 5アプリケーションでは、次のようなカスタム認証属性を使用しています。
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
if (context.HttpContext.Request.IsAuthenticated)
{
context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
}
else
{
base.HandleUnauthorizedRequest(context);
}
}
}
Web.configのsystem.web
セクションで、次のようなエラーパスに言及しました。
<system.web>
<customErrors mode="On" defaultRedirect="/Error/Error">
<error statusCode="403" redirect="/Error/NoPermissions"/>
</customErrors>
</system.web>
ただし、/Error/NoPermissions
のカスタムエラーページにリダイレクトされることはありません。代わりに、ブラウザは"HTTPエラー403.0-禁止"という一般的なエラーページを表示します。
みんなに感謝しますが、問題は403コードではありません。実際、問題は403を返そうとしていた方法にありました。HttpException
を返す代わりにHttpStatusCodeResult
をスローするようにコードを変更しただけで、すべてが動作するようになりました。 HttpException
例外をスローすることでHTTPステータスコードを返すことができ、私のcustomErrors
構成はそれらすべてをキャッチします。 HttpStatusCodeResult
が私が期待していた通りの仕事をしていない可能性があります。
私はちょうど交換しました
context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
と
throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Forbidden");
それでおしまい。
ハッピーコーディング。
[1]:Web.configからすべての 'customErrors'と 'httpErrors'を削除します
[2]:「App_Start/FilterConfig.cs」が次のようになっていることを確認します。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
[3]: 'Global.asax'に次のメソッドを追加します。
public void Application_Error(Object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Server.ClearError();
var routeData = new RouteData();
routeData.Values.Add("controller", "ErrorPage");
routeData.Values.Add("action", "Error");
routeData.Values.Add("exception", exception);
if (exception.GetType() == typeof(HttpException))
{
routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
}
else
{
routeData.Values.Add("statusCode", 500);
}
Response.TrySkipIisCustomErrors = true;
IController controller = new ErrorPageController();
controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
Response.End();
}
[4]:「Controllers/ErrorPageController.cs」を追加します
public class ErrorPageController : Controller
{
public ActionResult Error(int statusCode, Exception exception)
{
Response.StatusCode = statusCode;
ViewBag.StatusCode = statusCode + " Error";
return View();
}
}
[5]:「Views/Shared/Error.cshtml」内
@model System.Web.Mvc.HandleErrorInfo
@{
ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}
<h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>
//@Model.ActionName
//@Model.ControllerName
//@Model.Exception.Message
//@Model.Exception.StackTrace
:D
私もこの問題を抱えていました。 OPの質問のコードは、<system.web>
ファイルのweb.config
セクションのカスタムエラーコードを除き、完全に機能しています。この問題を解決するには、次のコードを<system.webServer>
に追加する必要がありました。 ‘webserver’
の代わりに‘web’
に注意してください。
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>
誰かが次の環境を使用している場合、完全なソリューションは次のとおりです。
環境:
カスタム属性クラス:
次のクラスをWebサイトのデフォルト名前空間に追加します。ここで受け入れられた答えで説明されている理由 スタックオーバーフローの質問:なぜAuthorizeAttributeは認証および承認の失敗のためにログインページにリダイレクトするのですか?
[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((int)System.Net.HttpStatusCode.Forbidden);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
次に、web.config
ファイルに次のコードを追加します
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>
</system.webServer>
次の記事で説明します これについての詳細:ASP.NET MVC:承認属性の改善(403禁止)
web.configのhttpErrorsこの記事のセクション: ASP.NET MVC 5のエラーページとエラーログをわかりやすく説明する
次に、ErrorController.csをControllersフォルダーに追加します
public class ErrorController : Controller
{
// GET: UnAuthorized
public ActionResult UnAuthorized()
{
return View();
}
public ActionResult Error()
{
return View();
}
}
次に、UnAuthorized.cshtmlをView/Sharedフォルダーに追加します
@{
ViewBag.Title = "Your Request Unauthorized !"; //Customise as required
}
<h2>@ViewBag.Title.</h2>
これにより、ブラウザで生成されたエラーページではなく、カスタマイズされたエラーページが表示されます。
また、上記の環境では、回答の1つで提案されているように、テンプレートによって追加されたRegisterGlobalFilters
メソッド内のコードをコメント化する必要はありません。
作業中のプロジェクトからコードをカットアンドペーストするだけなので、上記のコードではOPのUnauthorized
の代わりにNoPermissions
を使用したことに注意してください。
よく似た問題に遭遇したので、それをもっと明らかにしたかったのです。
customErrorsは、ASP.NETアプリケーションでスローされた実際のhttp例外のみをキャプチャします。ただし、HttpStatusCodeResultは例外をスローしません。それは、対応するステータスコードを使用して応答を書き込むだけです。これは、この例ではより意味があります。
IIS 7.0以降で実行している場合は、すべてのケースでカスタムエラーページが表示されるため、httpErrorsを使用する必要があります。これはIISレベル設定。
違いを説明するために、これに関するブログ記事全体を書きました: http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging
更新
403エラーに対してのみ、特別なリダイレクトを行う必要があります。他の500エラーはすべて、defaultRedirect="/Error/Error"
customErrors
の設定。ただし、カスタムエラーを実際に機能させるには、App_Start/FilterConfig.csファイルのHandleErrorAttribute登録を削除するかコメント化する必要があります。それ以外の場合、その属性はすべてのエラーをViews/SharedディレクトリのError.cshtmlファイルにリダイレクトします。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// remove this line below
//filters.Add(new HandleErrorAttribute());
}
}
元の回答
私が知る限り、何らかの理由でweb.configでcustomErrorsを使用して403エラーを処理することはできません。既に持っているコードと同じくらい単純なもののように思えますが、403エラーはWebサーバーの問題として扱われているように見えるので、あなたの痛みを感じます。
代わりにできることは、次のようにユーザーを目的の「NoPermissions」ページにリダイレクトするだけです。
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
if (context.HttpContext.Request.IsAuthenticated)
{
context.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
action = "NoPermissions",
controller = "Error",
area = ""
}));
}
else
{
base.HandleUnauthorizedRequest(context);
}
}
}
リクエストには、403ではなく200のステータスコードが含まれますが、それをそのまま使用できる場合、これは簡単な回避策です。
同様のSO詳細情報の質問: Returning custom errors 。
また、この記事では、IISルート: http://kitsula.com/Article/MVC-Custom-Error-Pages