【问题标题】:HttpPost to ReturnURL after redirect重定向后 HttpPost 到 ReturnURL
【发布时间】:2010-05-30 19:01:39
【问题描述】:

我正在编写一个 ASP.NET MVC 2.0 应用程序,该应用程序要求用户在出价之前登录。我正在使用 actionfilter 来确保用户已登录,如果没有,则将其发送到登录页面并设置返回 url。下面是我在操作过滤器中使用的代码。

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?

【问题讨论】:

    标签: c# asp.net-mvc http-post returnurl


    【解决方案1】:

    没有简单的方法可以做到这一点。我建议您将未经身份验证的用户重定向到登录页面,而不是在发布到某个 URL 时,而是在请求将发布到经过身份验证的 URL 的表单时。

    如果您知道您向未经身份验证的用户展示的表单将 POST 到网站的经过身份验证的部分,那么请不要向他展示该表单。当请求此表单时,只需重定向到登录页面进行身份验证,一旦通过身份验证重定向到原始表单。这样,您将确保只有经过身份验证的用户才会发布到受保护的资源。

    就自动 POST 请求(机器人程序、Web 服务等)而言,向不提供凭据的请求返回简单的 401 状态代码应该绰绰有余。

    【讨论】:

      【解决方案2】:

      我想我明白了为什么您希望身份验证仅针对出价 POST 操作。出价需要登录,但任何未登录的用户都可以看到拍卖页面。就像 ebay/amazon 等一样。在您根据用户要求付款或采取行动之前,一切都是可见的。

      如果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);
          }
      }
      

      【讨论】:

        【解决方案3】:

        可以写两个Controller方法同名,一个get一个post,记住TempData(或session)的get方法中的ReturnUrl,然后在post请求到达时从TempData中获取ReturnUrl:

        代码可能如下所示:

            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");
                        }
                    }
        

        ......

        肯定是当你第一次使用get操作到达页面时,然后将数据发布到服务器。

        我认为你也可以从 Request.UrlReferrer 获取整个 url。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-04-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-08
          • 1970-01-01
          • 2015-06-16
          相关资源
          最近更新 更多