1

自分のサイトのログイン関数をコーディングしています。ユーザーが私の属性で制限されているビューを要求すると、ユーザーはクエリ文字列が追加さ[CustomAuthorize]れたビューに正しくリダイレ​​クトされます( )。/Login/Index?ReturnUrl=%2fRestricted%2fView

しかし、ここに問題があります...

ユーザーがログインしようとしたときに、検証エラーが発生した場合。postリクエストによりpostback(duh)が発生し、追加されたクエリ文字列がURLから消えます。

  • ポストバック後にクエリ文字列を保持するにはどうすればよいですか?

CustomAuthorize.cs:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext.User.Identity.IsAuthenticated)
            {
                var customIdentity = (CustomIdentity)httpContext.User.Identity;
                var customPrincipal = new CustomPrincipal(customIdentity);

                if (customIdentity.IsAdmin)
                {
                    httpContext.User = customPrincipal;
                    Thread.CurrentPrincipal = customPrincipal;
                }
            }
            return base.AuthorizeCore(httpContext);
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            var urlRequested = filterContext.HttpContext.Request.Path;
            //urlRequested contains "/Restricted/View"
            //Do something with 'urlRequested' here, or?
            base.HandleUnauthorizedRequest(filterContext);
        }
}

ログイン/インデックスビュー:

<body>
        @using (Html.BeginForm("Index", "Login"))
        {
            <div>
                @Html.LabelFor(model => model.UserName)
            </div>
            <div>
                @Html.EditorFor(model => model.UserName)
                @Html.ValidationMessageFor(model => model.UserName)
            </div>

            <div>
                @Html.LabelFor(model => model.Password)
            </div>
            <div>
                @Html.EditorFor(model => model.Password)
                @Html.ValidationMessageFor(model => model.Password)
            </div>

            <div>
                @Html.LabelFor(model => model.RememberMe)
            </div>
            <div>
                @Html.EditorFor(model => model.RememberMe)
                @Html.ValidationMessageFor(model => model.RememberMe)
            </div>

            <p>
                <input type="submit" value="Login!" />
            </p>
            @Html.ValidationSummary(true)
        }
</body>

ログイン/インデックスコントローラのアクション:

[HttpPost]
public ActionResult Index(LoginModelBinding login, string returnUrl)
{
            if (ModelState.IsValid)
            {
                if (Service.CheckUser(login.UserName, login.Password))
                {
                    String loginError;
                    CustomAuthorization.Login(login.UserName, login.Password, out loginError);

                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("/\\"))
                    {
                        return Redirect(returnUrl);
                    }
                    return RedirectToAction("Index", "MitTeam");

                }
                ModelState.AddModelError("", "The entered user name or password is incorrect");
            }
            return View(login);
}

解決策: Naveenの回答に従って、次のようにコードを変更しました。

public static void SaveReturnUrl(this Controller controller, string returnUrl, bool showAfterRedirect = true)
{
            if (showAfterRedirect)
            {
                controller.TempData["returnUrl"] = returnUrl;
            }
            else
            {
                controller.ViewData["returnUrl"] = returnUrl;
            }
}

public static string RetrieveReturnUrl(this Controller controller)
{
            var message = controller.ViewData.ContainsKey("returnUrl") ? controller.ViewData["returnUrl"] : controller.TempData.ContainsKey("returnUrl") ? controller.TempData["returnUrl"] : null;
            return message as string;
}

これらの2つの拡張メソッドを使用して、LoginControllerメソッド/アクションでreturnurlを保存および取得できます。

ログイン投稿方法:

var previousReturnUrl = this.RetrieveReturnUrl();
if(!ModelState.IsValid)
{
    if(string.IsNullOrEmpty(previousReturnUrl))
    {
        this.SaveReturnUrl(returnUrl);
    }
    return View(login);
}

また、modelstateが有効な場合は、this.RetrieveReturnUrlそれを呼び出してデコードするだけなので、ログインに成功した場合にユーザーをリダイレクトできます。

4

2 に答える 2

1

MartijnBolandによって開発されたコードモジュールを使用できます-ユーザーに情報を提供し続けます。任意のオブジェクトを保存し、リダイレクト後にそれをフェッチするために使用できます。これは、POST-REDIRECT操作後の操作のメッセージまたはステータスを表示するために特に使用されました。これは、AJAXタイプのリクエストでも機能します。

リダイレクトを行った後、メッセージと一緒にリターンURLを保存するために同じものを使用できます(認証が失敗した場合)。

于 2012-04-22T06:54:21.317 に答える
0

ビューの非表示フィールドにreturnURLを保存できます。サーバーにポストバックされないフォームにその非表示フィールドを含める限り、POST-Actionは、アクションの結果に応じてアクセスして使用できます(ログイン成功-> URLへのリダイレクト、ログイン失敗->戻り再び隠しフィールドでログインビュー)。

于 2012-04-20T10:32:22.950 に答える