2010-05-30 35 views
5

Estoy escribiendo una aplicación ASP.NET MVC 2.0 que requiere que los usuarios inicien sesión antes de realizar una oferta en un artículo. Estoy usando un filtro de acción para asegurarme de que el usuario haya iniciado sesión y, si no, envíelos a una página de inicio de sesión y configure la url de retorno. A continuación está el código que uso en mi filtro de acción.HttpPost to ReturnURL after redirect

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

En mi controlador de inicio de sesión que validar las credenciales de los usuarios a continuación firman adentro y redirigir a la URL de retorno

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

Mi problema es que esto siempre utilizará una petición GET (HttpGet), mientras que mi original el envío fue una publicación (HttpPost) y siempre debe ser una publicación. ¿Alguien puede sugerir una manera de pasar esta URL incluyendo HttpMethod o cualquier solución para asegurarse de que se utiliza el HttpMethod correcto?

Respuesta

7

No hay una manera fácil de hacer esto. Lo que le recomendaría es redirigir a los usuarios no autenticados a la página de inicio de sesión, no al publicar en alguna URL, sino al solicitar el formulario que PUBLICARÁ a la URL autenticada.

Si sabe que el formulario que está presentando a un usuario no autenticado se ENVIARÁ a una parte autenticada del sitio, bueno, no le presente el formulario. Cuando se solicita este formulario simplemente redirigir a la página de inicio de sesión para la autenticación y una vez autenticado redirigir a la forma original. De esta forma, se asegurará de que solo los usuarios autenticados PUBLICARÁN al recurso protegido.

En cuanto a las solicitudes POST automáticas (bots, servicios web, ...) devolver un código de estado simple 401 a las solicitudes que no proporcionan credenciales debe ser más que suficiente.

7

Creo que entiendo por qué quieres que la autenticación solo esté en la acción de la oferta POST. Una oferta requiere inicio de sesión, pero cualquier usuario que no haya iniciado sesión puede ver la página de la subasta. Al igual que ebay/amazon, etc. Todo es visible hasta que requiera un pago o acción en función de un usuario.

Usted puede cambiar su atributo a su lugar devolver el Request.UrlReferrer a la página de inicio de sesión si el Request.RequestType es una POST. Luego serían redirigidos a la página de subastas y pueden volver a hacer clic en la oferta una vez que inicien sesión. Incluso podría pasar cierto campo, digamos cantidad, con el UrlReferrer para que pueda volver a llenar el campo de cantidad una vez que lleguen al página de subasta. Puede obtener ese campo de la colección 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

Puede escribir dos métodos de controlador con el mismo nombre, pero uno para get y otra para el poste, y recordar el ReturnUrl en el método get en TempData (o sesión), y luego obtener el ReturnUrl de TempData cuando solicitud POST llega:

el código puede ve así:

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

......

es definitivamente la primera vez que llega a la página de usando get action, luego publica datos en el servidor.

Creo que también puede obtener toda la URL de Request.UrlReferrer.