96

クライアントのページをホストするマルチテナンシーWebサイトを作成しています。URLの最初のセグメントは、次のURLルーティングスキームを使用してGlobal.asaxで定義されたクライアントを識別する文字列になります。

"{client}/{controller}/{action}/{id}"

これは、/ foo / Home/IndexなどのURLで正常に機能します。

ただし、[Authorize]属性を使用する場合、同じマッピングスキームを使用するログインページにリダイレクトしたいと思います。したがって、クライアントがfooの場合、ログインページはweb.configで定義された固定の/ Account / Loginリダイレクトではなく、/ foo / Account/Loginになります。

MVCはHttpUnauthorizedResultを使用して401の不正なステータスを返します。これにより、ASP.NETはweb.configで定義されたページにリダイレクトされると思います。

では、ASP.NETログインリダイレクトの動作をオーバーライドする方法を知っている人はいますか?または、カスタム認証属性を作成してMVCでリダイレクトする方がよいでしょうか?

編集-回答: .Netソースを掘り下げた後、カスタム認証属性が最善の解決策であると判断しました:

public class ClientAuthorizeAttribute: AuthorizeAttribute
{
    public override void OnAuthorization( AuthorizationContext filterContext )
    {
        base.OnAuthorization( filterContext );

        if (filterContext.Cancel && filterContext.Result is HttpUnauthorizedResult )
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "client", filterContext.RouteData.Values[ "client" ] },
                    { "controller", "Account" },
                    { "action", "Login" },
                    { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
                });
        }
    }
}
4

4 に答える 4

41

ASP.NET MVC の RTM バージョンでは、Cancel プロパティがありません。このコードは ASP.NET MVC RTM で動作します。

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Resources;

namespace ePegasus.Web.ActionFilters
{
    public class CustomAuthorize : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
            if (filterContext.Result is HttpUnauthorizedResult)
            {
                filterContext.Result = new RedirectToRouteResult(
                    new System.Web.Routing.RouteValueDictionary
                        {
                                { "langCode", filterContext.RouteData.Values[ "langCode" ] },
                                { "controller", "Account" },
                                { "action", "Login" },
                                { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
                        });
            }
        }
    }
}

編集: web.config でデフォルトのフォーム認証 loginUrl を無効にすることをお勧めします - 誰かがカスタム属性を持っていることを忘れて、組み込みの [Authorize] 属性を誤って使用した場合に備えて。

web.config の値を変更します。

 <forms loginUrl="~/Account/ERROR" timeout="2880" />

次に、エラーをログに記録し、ユーザーを最も一般的なログイン ページにリダイレクトするアクション メソッド「ERROR」を作成します。

于 2009-07-08T13:38:18.740 に答える
30

主な問題は、組み込みのASP.NET FormsAuthenticationクラスに便乗する場合(そして、そうすべきでない正当な理由がない場合)、1日の終わりに何かが呼び出されることだと思いますFormsAuthentication.RedirectToLoginPage()。構成された1つのURLを確認します。ログインURLはこれまでに1つしかなく、それが彼らが設計した方法です。

問題(おそらくRube Goldbergの実装)での私の刺し傷は、すべてのクライアントが共有するルートの単一のログインページ(たとえば/ account / login)にリダイレクトできるようにすることです。このログインページには実際には何も表示されません。ReturnUrlパラメータ、セッションで取得した値、またはクライアントを識別するCookieを検査し、それを使用して特定の/ client / account/loginページへの即時302リダイレクトを発行します。これは余分なリダイレクトですが、目立たない可能性が高く、組み込みのリダイレクトメカニズムを使用できます。

RedirectToLoginPage()もう1つのオプションは、説明するときに独自のカスタム属性を作成し、クラスのメソッドを呼び出すものを回避することFormsAuthenticationです。これは、独自のリダイレクトロジックに置き換えるためです。(同様の独自のクラスを作成することもできます。)これは静的クラスであるため、独自の代替インターフェイスを挿入して、既存の[Authorize]属性で魔法のように機能させるメカニズムを認識していません。打撃がありますが、人々は以前に同様のことをしました。

お役に立てば幸いです。

于 2008-12-11T06:16:22.987 に答える
2

この問題に対する私の解決策は、カスタムActionResultクラスでした。

    sealed public class RequiresLoginResult : ActionResult
    {
        override public void ExecuteResult (ControllerContext context)
        {
            var response = context.HttpContext.Response;

            var url = FormsAuthentication.LoginUrl;
            if (!string.IsNullOrWhiteSpace (url))
                url += "?returnUrl=" + HttpUtility.UrlEncode (ReturnUrl);

            response.Clear ();
            response.StatusCode = 302;
            response.RedirectLocation = url;
        }

        public RequiresLoginResult (string returnUrl = null)
        {
            ReturnUrl = returnUrl;
        }

        string ReturnUrl { get; set; }
    }
于 2010-07-16T15:35:26.610 に答える