2010-05-30 10 views
5

Ich schreibe eine ASP.NET MVC 2.0-Anwendung, die Benutzer anmelden müssen, bevor Sie ein Gebot auf ein Element platzieren. Ich verwende einen Actionfilter, um sicherzustellen, dass der Benutzer eingeloggt ist, und, falls nicht, sende ihn an eine Login-Seite und setze die Return-URL. Unten ist der Code, den ich in meinem Aktionsfilter verwende.HttpPost zu ReturnURL nach Umleitung

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

In meinem Anmelde Controller validieren ich die Benutzer-Anmeldeinformationen unterzeichnen sie dann in und Umleitung auf die Rückkehr url

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

Mein Problem ist, dass dies immer ein Get (HttpGet) Anfrage während meiner ursprünglichen verwenden Vorlage war ein Beitrag (HttpPost) und sollte immer ein Beitrag sein. Kann jemand vorschlagen, diese URL einschließlich der HttpMethod oder einer anderen Problemumgehung zu übergeben, um sicherzustellen, dass die richtige HttpMethod verwendet wird?

Antwort

7

Es gibt keine einfache Möglichkeit, dies zu tun. Ich würde Ihnen empfehlen, die nicht authentifizierten Benutzer auf die Anmeldeseite umzuleiten, nicht wenn Sie eine URL bereitstellen, sondern wenn Sie das Formular anfordern, das an die authentifizierte URL gesendet wird.

Wenn Sie wissen, dass das Formular, das Sie einem nicht authentifizierten Benutzer präsentieren, POST an einen authentifizierten Teil der Site sendet, dann stellen Sie ihm das Formular nicht zur Verfügung. Wenn dieses Formular angefordert wird, leiten Sie einfach auf die Anmeldeseite zur Authentifizierung und einmal authentifizierte Weiterleitung zum ursprünglichen Formular um. Auf diese Weise stellen Sie sicher, dass nur authentifizierte Benutzer an die geschützte Ressource senden.

Soweit automatisierte POST-Anfragen betroffen sind (Bots, Webdienste, ...), die einen einfachen 401-Statuscode an Anfragen zurückgeben, die keine Anmeldeinformationen bereitstellen, sollte mehr als ausreichend sein.

7

Ich denke, ich bekomme, warum Sie die Authentifizierung nur auf das Gebot POST Aktion wollen. Ein Gebot erfordert eine Anmeldung, aber alle nicht angemeldeten Nutzer können die Auktionsseite sehen. Genau wie ebay/amazon etc. Alles ist sichtbar, bis Sie eine Zahlung oder Aktion auf der Grundlage eines Benutzers benötigen.

Sie können Ihr Attribut ändern, um stattdessen an die Anmeldeseite zu senden, wenn die Request.RequestType eine POST ist. Dann würden sie auf die Auktionsseite umgeleitet und können erneut klicken, sobald sie eingeloggt sind. Sie könnten sogar ein bestimmtes Feld, zB Betrag, mit der Nummer UrlReferrer weiterleiten, so dass Sie das Betragsfeld wieder füllen könnten, sobald sie auf dem Land landen Auktionsseite. Sie können dieses Feld aus der Request.Form Sammlung abrufen.

// 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

Sie können zwei Controller-Methoden mit dem gleichen Namen schreiben, aber einen für get und eine andere für die Post, und erinnern dich an die ReturnUrl in der get-Methode in TempData (oder Sitzung), und dann die ReturnUrl von TempData erhalten, wenn Post-Anforderung ankommt:

der Code kann wie folgt aussieht:

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 ist auf jeden Fall, wenn Sie zuerst auf die Seite kommt durch Verwenden Sie get action, und veröffentlichen Sie dann Daten auf dem Server.

Ich denke, Sie können auch die gesamte URL von Request.UrlReferrer erhalten.