2010-05-30 36 views
5

我正在寫一個ASP.NET MVC 2.0應用程序,它要求用戶在投標項目前登錄。我正在使用actionfilter來確保用戶已登錄,如果沒有,則將它們發送到登錄頁面並設置返回URL。以下是我在我的動作過濾器中使用的代碼。HttpPost重定向後ReturnURL

if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
{ 
    filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn","?ReturnUrl=",filterContext.HttpContext.Request.RawUrl)); 
    return; 
} 

在我登錄控制器我驗證用戶的證書,那麼他們簽名並重定向到返回URL

FormsAuth.SignIn(userName, rememberMe); 
if (!String.IsNullOrEmpty(returnUrl)) 
{ 
    return Redirect(returnUrl); 
} 

我的問題是,這將始終使用,而我原來的一個Get(HTTPGET)要求提交是一個帖子(HttpPost),應該始終是帖子。任何人都可以提出一種傳遞此URL的方法,包括HttpMethod或任何解決方法以確保使用正確的HttpMethod?

回答

7

有沒有簡單的方法來做到這一點。我建議你將未經身份驗證的用戶重定向到登錄頁面,而不是在發佈到某個URL時,而是在請求將發佈到經過身份驗證的URL的表單時。

如果您知道您向未經身份驗證的用戶呈現的表單將張貼到網站的經過身份驗證的部分,那麼請不要將表單呈現給他。當請求這個表單時,只需重定向到登錄頁面進行身份驗證,並且一旦通過身份驗證,就會重定向到原始表單。這樣您將確保只有經過身份驗證的用戶纔會向受保護的資源發佈POST。

就自動POST請求而言(機器人,Web服務......)將簡單的401狀態碼返回給不提供憑證的請求應該是綽綽有餘的。

7

我想我得到你爲什麼要驗證只在出價POST行動。出價需要登錄,但任何未登錄的用戶都可以看到拍賣頁面。就像易趣/亞馬遜等一切都是可見的,直到你需要付費或基於用戶的行動。

如果Request.RequestTypePOST,您可以將您的屬性更改爲返回Request.UrlReferrer登錄頁面。然後,他們將被重定向到拍賣頁面,並且可以在登錄後再次點擊出價。您甚至可以通過UrlReferrer傳遞某個字段(如金額),以便您可以在金額字段落入拍賣頁面。您可以從Request.Form集合中獲取該字段。

// in usage...  
[RequireLogin(AdditionalFields="amount,someotherfield")] 
[HttpPost] 
public ActionResult Bid(.....) 

// the attribute 
class RequireLoginAttribute : ActionFilterAttribute 
{ 
    public string AdditionalFields { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      var returnUrl = filterContext.HttpContext.Request.RawUrl; 
      if (filterContext.HttpContext.Request.RequestType == "POST") 
      { 
       returnUrl = filterContext.HttpContext.Request.UrlReferrer.PathAndQuery; 
       // look for FORM values in request to append to the returnUrl 
       // this can be helpful for a good user experience (remembering checkboxes/text fields etc) 
      } 

      filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn", "?ReturnUrl=", returnUrl)); 
      return; 
     } 
     base.OnActionExecuting(filterContext); 
    } 
} 
2

你可以寫兩個控制器方法具有相同的名稱,但一個get和另一個用於後,記得在TempData的(或會話)GET方法RETURNURL,然後從TempData的時候得到RETURNURL POST請求到達時:

五月代碼如下所示:

public ActionResult LogOn(string returnUrl) 
    { 
     if (!string.IsNullOrEmpty(returnUrl)) 
     { 
      TempData["ReturnUrl"] = returnUrl; 
     } 
     return View(); 
    } 

    [HttpPost] 
    public ActionResult LogOn(LogOnModel model, FormCollection collecton) 
    { 
     if (ModelState.IsValid) 
     { 
      AuthenticationResult logonStatus = TransactionScriptFactory.GetTransactionScript<UserTransactionScripts>() 
                     .LogOn(model.Email, model.Password); 

      if (logonStatus.AuthResult == AuthResultEnum.Success) 
      { 
       FormsService.SignIn(logonStatus.User.UserId, logonStatus.User.NickName, false); 

       object returnUrl = string.Empty; 
       TempData.TryGetValue("ReturnUrl", out returnUrl); 
       string returnUrlStr = returnUrl as string; 
       if (!string.IsNullOrEmpty(returnUrlStr)) 
       { 
        return Redirect(returnUrlStr); 
       } 
       else 
       { 
        return RedirectToAction("Index", "Home"); 
       } 
      } 

......

這是defintely當你第一次到達的頁面通過使用獲取操作,然後將數據發佈到服務器。

我想你也可以從Request.UrlReferrer獲得整個網址。