HttpPost для возврата URL после перенаправления

Я пишу приложение ASP.NET MVC 2.0, которое требует, чтобы пользователи входили в систему, прежде чем делать ставку на товар. Я использую фильтр действий, чтобы убедиться, что пользователь вошел в систему, и, если нет, отправить их на страницу входа и установить 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?


person JP.    schedule 30.05.2010    source источник


Ответы (3)


Нет простого способа сделать это. Я бы порекомендовал вам перенаправить неаутентифицированных пользователей на страницу входа не при публикации на какой-либо URL-адрес, а при запросе формы, которая будет отправлять POST на аутентифицированный URL-адрес.

Если вы знаете, что форма, которую вы предоставляете неаутентифицированному пользователю, будет отправлена ​​в аутентифицированную часть сайта, что ж, не предоставляйте ему форму. Когда эта форма запрашивается, просто перенаправьте на страницу входа для аутентификации и после аутентификации перенаправьте на исходную форму. Таким образом вы гарантируете, что только аутентифицированные пользователи будут отправлять POST на защищенный ресурс.

Что касается автоматических запросов POST (ботов, веб-сервисов и т. д.), то возврата простого кода состояния 401 на запросы, которые не предоставляют учетные данные, должно быть более чем достаточно.

person Darin Dimitrov    schedule 30.05.2010

Думаю, я понимаю, почему вы хотите, чтобы аутентификация была только в действии ставки POST. Ставка требует входа в систему, но любой пользователь, не вошедший в систему, может видеть страницу аукциона. Так же, как ebay/amazon и т. д. Все видно, пока вы не потребуете оплаты или действия на основе пользователя.

Вы можете изменить свой атрибут, чтобы вместо этого возвращать Request.UrlReferrer на страницу входа, если Request.RequestType является POST. Затем они будут перенаправлены на страницу аукциона и смогут снова щелкнуть ставку после того, как войдут в систему. Вы даже можете передать определенное поле, скажем, сумму, с помощью 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);
    }
}
person Jab    schedule 01.06.2010

Вы можете написать два метода контроллера с одинаковым именем, но один для получения, а другой для публикации, и запомнить ReturnUrl в методе получения в TempData (или сеансе), а затем получить ReturnUrl из TempData при поступлении почтового запроса:

Код может выглядеть так:

    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, а затем отправляете данные на сервер.

Я думаю, вы также можете получить полный URL-адрес из Request.UrlReferrer.

person Pu Wang    schedule 20.11.2010