重定向后 HttpPost 到 ReturnURL

发布于 2024-09-03 08:30:10 字数 682 浏览 9 评论 0原文

我正在编写一个 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?

I am writing an ASP.NET MVC 2.0 application which requires users to log in before placing a bid on an item. I am using an actionfilter to ensure that the user is logged in and, if not, send them to a login page and set the return url. Below is the code i use in my action filter.

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

In my logon controller I validate the users credentials then sign them in and redirect to the return url

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

My problem is that this will always use a Get (HttpGet) request whereas my original submission was a post (HttpPost) and should always be a post. Can anyone suggest a way of passing this URL including the HttpMethod or any workaround to ensure that the correct HttpMethod is used?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沦落红尘 2024-09-10 08:30:11

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

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

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

There's no easy way to do this. What I would recommend you is to redirect the unauthenticated users to the login page not when posting to some URL but when requesting the form that will POST to the authenticated URL.

If you know that the form you are presenting to an unauthenticated user will POST to an authenticated part of the site, well, don't present him the form. When this form is requested simply redirect to the login page for authentication and once authenticated redirect to the original form. This way you will ensure that only authenticated users will POST to the protected resource.

As far as automated POST requests are concerned (bots, web services, ...) returning a simple 401 status code to requests that do not provide credentials should be more than sufficient.

剩一世无双 2024-09-10 08:30:11

我想我明白为什么您希望仅在出价 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);
    }
}

I think I get why you want the authentication to only be on the bid POST action. A bid requires login, but any non-logged in user can see the auction page. Just like ebay/amazon etc. Everything is visible until you require payment or action based on a user.

You could change your attribute to instead return the Request.UrlReferrer to the login page if the Request.RequestType is a POST. Then they would be redirected to the auction page and can click bid again once they are logged in. You could even pass along a certain field, say amount, with the UrlReferrer so that you could re-populate the amount field once they land on the auction page. You could get that field from the Request.Form collection.

// 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);
    }
}
冰火雁神 2024-09-10 08:30:11

你可以编写两个同名的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。

You can write two Controller methods with the same name, but one for get and another for post, and remember the ReturnUrl in the get method in TempData(or session), and then get the ReturnUrl from TempData when post request arrives:

The code may looks like this:

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

......

It is defintely when you first arrives to the page by using get action, then post data to server.

I think you can also get the whole url from Request.UrlReferrer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文