私はAuthorize
属性を次のように使用しています:
[Authorize (Roles="Admin, User")]
Public ActionResult Index(int id)
{
// blah
}
ユーザーが指定されたロールにない場合、エラーページが表示されます(リソースが見つかりません)。それで、HandleError
属性も入れました。
[Authorize (Roles="Admin, User"), HandleError]
Public ActionResult Index(int id)
{
// blah
}
これで、ユーザーが指定されたロールにない場合、ログインページに移動します。
ユーザーが必要な役割の1つを満たさない場合に、ログインページではなくnauthorizedページに移動するにはどうすればよいですか?また、別のエラーが発生した場合、そのエラーを未承認のエラーと区別して、異なる方法で処理するにはどうすればよいですか?
次のようなものをweb.configに追加します。
<customErrors mode="On" defaultRedirect="~/Login">
<error statusCode="401" redirect="~/Unauthorized" />
<error statusCode="404" redirect="~/PageNotFound" />
</customErrors>
/PageNotFound
と/Unauthorized
のルート、アクション、ビューを作成する必要があります。
[〜#〜] edit [〜#〜]:すみません、問題を完全に理解していないようです。
問題は、AuthorizeAttribute
フィルターが実行されると、ユーザーが要件に適合しないと判断することです(ユーザーはログインしている可能性がありますが、正しい役割ではありません)。したがって、応答ステータスコードを401に設定します。これは、リダイレクトを実行するFormsAuthentication
モジュールによってインターセプトされます。
2つの選択肢があります。
DefaultRedirectを無効にします。
独自のIAuthorizationFilter
を作成します。 AuthorizeAttribute
から派生し、HandleUnauthorizedRequestをオーバーライドします。この方法では、ユーザーが認証されている場合、redirectを/ Unauthorizedに実行します
私も好きではありません。defaultRedirect機能はニースであり、自分で実装したいものではありません。 2番目の方法では、ユーザーに視覚的に正しい「あなたは認証されていません」ページが表示されますが、HTTPステータスコードは必要な401ではありません。
許容できるハックでこれを回避できるかどうかについては、HttpModulesについて十分に知りません。
編集2:次の方法で独自のIAuthorizationFilterを実装するのはどうですか。CodePlexからMVC2コードをダウンロードし、AuthorizeAttributeのコードを「借りる」。 OnAuthorizationメソッドを次のように変更します
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
// Is user logged in?
else if(filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// Redirect to custom Unauthorized page
filterContext.Result = new RedirectResult(unauthorizedUrl);
}
else {
// Handle in the usual way
HandleUnauthorizedRequest(filterContext);
}
}
ここで、unauthorizedUrl
はフィルターのプロパティか、Web.configから読み取られます。
AuthorizeAttributeを継承してOnAuthorization
をオーバーライドすることもできますが、すでにAuthorizeAttributeにあるいくつかのプライベートメソッドを作成することになります。
これは、次の2つの方法で実行できます。
エラーのHandleError属性を指定し、表示する必要のあるビューを指定します。
[HandleError(ExceptionType = typeof(UnAuthorizedException)、View = "UnauthorizedError")]
いくつかの異なるExceptionTypeとビューを指定できます
おそらく、403ステータスコードは、質問に基づいてより適切です(ユーザーは識別されますが、アカウントには十分な特権がありません)。 401は、ユーザーが持っている特権がわからない場合に使用します。
そしてHttpUnauthorizedResult
(これはAuthorizeAtrribute
の再利用として提供されます)はStatusCodeを401に設定するだけです。したがって、おそらくIISまたはweb.config。もちろん、カスタムエラーページへのアクセスが承認を必要としないことを確認する必要もあります。
AuthorizeAttributeのHandleUnauthorizedRequestメソッドをオーバーライドするだけです。このメソッドが呼び出されても、ユーザーIS=認証されている場合は、「承認されていない」ページにリダイレクトできます。
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { Area = "", Controller = "Error", Action = "Unauthorized" }));
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}