2012-12-18 93 views
1

我建立使用MVC 4單頁的應用程序對於登錄的功能我做一個jquery ajax的POST到這個動作:純AJAX MVC 4驗證

[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」在任何網站或者說登錄/註冊,如果用戶沒有通過驗證或註銷/歡迎,如果他們是頂部的標準吧:

@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仍然是一樣的前t o ajax調用,所以它不會重新呈現正確的狀態欄,直到下一個請求。

我怎樣才能解決這個問題,因爲Request.IsAuthenticated是隻讀的,我不能簡單地在設置授權cookie後設置它。我能做的就是,而不是設置的TempData屬性,檢查渲染,而不是當UserStatusBar的唯一的事:

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

但由於註銷時情況相反,這是有問題的; Request.IsAuthenticatedformsAuthentication.SignOut()之後仍然爲真,當狀態欄重新呈現時,它會再次呈現狀態欄的錯誤標記,直到下一個請求。

我似乎無法想出解決此問題的一種方法,因爲我也需要固定鏈接才能工作,所以Request.IsAuthenticated是我在這種情況下要查看的一個。

回答

1

好的,我找到了我的答案。我編寫了一個控制器擴展,它根據當前響應中的cookie(在成功授權之後設置並在調用此方法之前)更新當前請求的安全主體。立即更新Request.IsAuthenticated

注意:我正在使用自定義成員資格,因此此代碼不會爲您逐字處理。

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[] {}); 
     } 
    }