1

MVC 4 を使用して単一ページのアプリケーションを構築しています。ログイン機能については、このアクションに対して jquery ajax POST を実行します。

    [HttpPost] [AllowAnonymous]
    public JsonResult JsonLogin(LogInFormViewModel form)
    {
         ...

         //If user authenticates
            formAuthentication.SetAuthCookie(this.HttpContext,
                                                 UserAuthenticationTicketBuilder.CreateAuthenticationTicket(
                                                                 user));
            return Json(new { success = true, viewResult = this.RenderPartialView("UserStatusBar", null) });

         ...

    }

RenderPartialView()かみそりの部分ビューを文字列にレンダリングするだけのカスタム拡張です。

「UserStatusBar」は、Web サイトの上部にある標準バーで、ユーザーが認証されていない場合はログイン/登録、認証されていない場合はログオフ/ようこそと表示されます。

@if (Request.IsAuthenticated)
{
    <div id="LoggedIn">
        <a class="logoutLink" href="#">Log out</a>
        <span>Welcome, @User.Identity.Name</span>
    </div>
} else {
    <div id="notLoggedIn">
        <a class="loginLink popupLink" href="#">Log in</a>
        <a class="registerLink popupLink" href="#">Register</a>
    </div>
}

私の ajax 成功ハンドラーでは、ユーザーがログインまたはログオフした後にユーザー ステータス バーだけを非同期的に再レン​​ダリングするために、次のようなことを行います。

success: function (result) {
    if (result.success) {
       $('#userStatusBar').empty().html(result.viewResult, null);
    }
}

唯一の問題は、コードがカスタム拡張機能にステップインするたびRenderPartialView()Request.IsAuthenticated、ajax 呼び出しの前と同じままであるため、次のリクエストまで正しいステータス バーを再レンダリングしないことです。

Request.IsAuthenticated読み取り専用であるため、認証Cookieを設定した後に簡単に設定できないため、これを回避するにはどうすればよいですか。私ができる唯一のことは、代わりに TempData プロパティを設定し、代わりに UserStatusBar をレンダリングするときにそれを確認することです。

@if (Request.IsAuthenticated || (TempData["AjaxAuthenticated"] != null && (bool)TempData["AjaxAuthenticated"]))
{
    <logged in html>
} else <logged out html>

しかし、ログオフすると逆のことが起こるため、これには問題があります。ステータスバーが再レンダリングされたRequest.IsAuthenticated後もまだ真であり、次のリクエストまでステータスバーの誤ったマークアップを再度レンダリングします。formsAuthentication.SignOut()

私はこれを回避する方法を考えられないようです。なぜなら、パーマリンクが機能する必要があるためです。

4

1 に答える 1

1

わかりました私は私の答えを見つけました。現在の応答の Cookie に基づいて、現在の要求のセキュリティ プリンシパルを更新するコントローラー拡張機能を作成しました (認証が成功した後、このメソッドを呼び出す直前に設定されます)。これRequest.IsAuthenticatedはすぐに true に更新されます。

注: カスタム メンバーシップを使用しているため、このコードはそのままでは機能しません。

    public static void AjaxRenewPrincipal(this Controller controller)
    {
        HttpCookie authCookie = controller.HttpContext.Response.Cookies[FormsAuthentication.FormsCookieName];
        if (IsValidAuthCookie(authCookie))
        {
            var formsAuthentication = DependencyResolver.Current.GetService<IFormsAuthentication>();
            var authTicket = formsAuthentication.Decrypt(authCookie.Value);

            CustomUser user = new CustomUser(authTicket); //An authenticated user
            string[] userRoles = { user.RoleName };
            controller.HttpContext.User = new GenericPrincipal(user , userRoles);
            formsAuthentication.SetAuthCookie(controller.HttpContext, authTicket);
        }
        else
        {
            //using Parameter-less constructor on my CustomClass : IIdentity sets IsAuthenticated to false on the IIdentity, then unauthenticated user gets set to the security principal
            controller.HttpContext.User = new GenericPrincipal(new CustomUser (), new string[] {});
        }
    }
于 2012-12-18T09:41:38.367 に答える