重定向后 HttpPost 到 ReturnURL
-
05-10-2019 - |
题
我正在编写一个 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;
}
在我的登录控制器中,我验证用户凭据,然后将其登录并重定向到返回网址
FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
我的问题是,这将始终使用 Get (HttpGet) 请求,而我最初的提交是一个帖子 (HttpPost),并且应该始终是一个帖子。任何人都可以建议一种传递此 URL 的方法(包括 HttpMethod)或任何解决方法以确保使用正确的 HttpMethod?
解决方案
没有简单的方法可以做到这一点。我建议您将未经身份验证的用户重定向到登录页面,而不是在发布到某个 URL 时,而是在请求将 POST 到经过身份验证的 URL 的表单时。
如果您知道向未经身份验证的用户提供的表单将 POST 到网站的经过身份验证的部分,那么就不要向他提供该表单。当请求此表单时,只需重定向到登录页面进行身份验证,并在经过身份验证后重定向到原始表单。这样您就可以确保只有经过身份验证的用户才会 POST 到受保护的资源。
就自动 POST 请求(机器人、Web 服务等)而言,向不提供凭据的请求返回简单的 401 状态代码应该足够了。
其他提示
我想我明白了为什么您希望身份验证只能出价 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);
}
}
您可以编写两个具有相同名称的控制器方法,但一个用于get,另一个用于邮寄,并记住tempdata(或session)中的get方法中的returnUrl,然后在邮政请求到达时从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");
}
}
......
当您首次使用“获取操作”首次到达页面时,然后将数据发布到服务器中。
我认为您还可以从request.urlreferrer获取整个URL。