.NET 4.5 と IIS 8 を使用する MVC4 アプリケーションを使用しています。許可チェックが失敗したときに、カスタムの未承認ページと 401 結果を返す方法はありますか?
フォーム認証も使用しており、ユーザーがログインしていない場合はログイン ページにリダイレクトしたいが、ユーザーが有効な権限 (管理者など) を持っていない場合は、承認されていないページにリダイレクトしたい。
また、リダイレクトに注意し、リダイレクトが成功したときに 200/301 の結果を達成する必要があります。
401 ステータス コードを返し、現在のページにとどまる一方で、カスタムの未承認ページも返す必要があります。
許可されていないビューを返すエラー コントローラーがあります。
[ActionName("unauthorised")]
public ActionResult Http401() {
Response.StatusCode = 401;
Response.StatusDescription = "Unauthorised";
Response.SuppressFormsAuthenticationRedirect = true;
return View("unauthorised");
}
また、パーミッションのチェックが失敗した場合に 401 を呼び出すために使用しているメソッドがいくつかあります。
/// <summary>Method to invoke when user attempts action without relevant permission</summary>
/// <param name="httpContext">the httpcontext</param>
/// <returns>empty result</returns>
public ActionResult InvokeHttp401(HttpContextBase httpContext) {
Transfer("/error/unauthorised");
return new EmptyResult();
}
private void Transfer(string url) {
var uriBuilder = new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port, Request.ApplicationPath); // Create URI builder
uriBuilder.Path += url; // Add destination URI
string path = Server.UrlDecode(uriBuilder.Uri.PathAndQuery); // Because UriBuilder escapes URI decode before passing as an argument
this.HttpContext.RewritePath(path, false); // Rewrite path
HttpContext.Server.TransferRequest(path, true);
}
注: 私は Server.TransferRequest を使用しているため、リダイレクトを発生させることなく、現在の URL で 401 の結果を返すことができます。次のように、通常の ActionResult で許可を確認しています。
[Authorize]
public ActionResult MyMethod() {
if (!UserHasPermission(Admin))
return InvokeHttp401(HttpContext);
......
ユーザーがログインしていない場合に認証タグがログインにリダイレクトする場所で、その他の権限チェックが行われます。
上記のセットアップでは、401 の結果を返し、現在の URL にとどまることができますが、現在のページではなく IIS 401 エラーが表示されます。
また、web.config ファイルで次のように設定しようとしました。
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace">
.....
<error statusCode="401" responseMode="ExecuteURL" path="/Error/unauthorised" />
</httpErrors>
しかし、これは違いはありません。Http401 ActionResult にステータス コードを設定しないと、カスタムの無許可ページを表示できますが、その場合は 200 の結果が返されます。
この質問に関する投稿(特に、認証タグを拡張したティモシーの回答)を見てきましたが、すでに説明したのと同様のエラーがなければ、これを機能させることができませんでした。
誰でもここで助けることができますか?