Domanda

Sto scrivendo un'applicazione ASP.NET MVC 2.0 che richiede agli utenti di accedere in prima di fare un'offerta su un elemento. Sto usando un ActionFilter per garantire che l'utente è connesso e, se non, inviarli ad una pagina di accesso e impostare l'URL di ritorno. Di seguito è riportato il codice che uso nel mio filtro azione.

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

Nel mio accesso controller I convalidare le credenziali degli utenti per poi accedere e reindirizzamento al ritorno url

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

Il mio problema è che questo sarà sempre utilizzare una richiesta GET (HttpGet), mentre la mia presentazione originale era un post (HttpPost) e dovrebbe essere sempre un post. Qualcuno può suggerire un modo di passare questo URL compreso il HttpMethod o qualsiasi soluzione per garantire che il corretto HttpMethod viene utilizzato?

È stato utile?

Soluzione

Non c'è modo semplice per farlo. Quello che mi sento di raccomandare voi è quello di reindirizzare gli utenti non autenticati alla pagina di login non quando annuncio a un certo URL, ma quando si richiede la forma che posterò all'URL autenticato.

Se si sa che il modulo che si sta presentando ad un utente non autenticato sarà POST ad una parte autenticata del sito, beh, non presentano lo forma. Quando viene richiesto questo modulo semplicemente reindirizzare alla pagina di accesso per l'autenticazione e una volta autenticato reindirizzamento alla forma originale. In questo modo si è sicuri che solo gli utenti autenticati pubblicheremo alla risorsa protetta.

Per quanto riguarda le richieste POST automatizzate sono interessati (bot, servizi web, ...) restituisce un codice di stato 401 semplice a richieste che non forniscono le credenziali dovrebbero essere più che sufficiente.

Altri suggerimenti

Credo di aver capito il motivo per cui si desidera che l'autenticazione per essere solo sull'azione offerta POST. Un'offerta richiede login, ma qualsiasi non-utenti registrati possono vedere la pagina dell'asta. Proprio come ebay / amazon ecc Tutto è visibile fino a quando si richiede il pagamento o l'azione sulla base di un utente.

Si potrebbe cambiare l'attributo di restituire invece il Request.UrlReferrer alla pagina di login se il Request.RequestType è un POST. Poi sarebbero stati reindirizzati alla pagina dell'asta e possono fare clic su un'offerta di nuovo una volta che sono connessi. Si potrebbe anche passare lungo un determinato campo, ad esempio quantità, con il UrlReferrer in modo che si potrebbe ri-popolare il campo importo una volta che atterrano sul pagina dell'asta. Si potrebbe ottenere quel campo dalla collezione 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);
    }
}

È possibile scrivere due metodi di controllo con lo stesso nome, ma uno per ottenere e un altro per il post, e ricordare il ReturnUrl nel metodo get a TempData (o della sessione), e quindi ottenere il ReturnUrl da TempData quando richiesta POST arriva:

Il codice può assomiglia a questo:

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

......

E 'sicuramente quando si arriva prima alla pagina utilizzando l'azione get, i dati poi posta al server.

Penso che si può anche ottenere l'intera URL dal Request.UrlReferrer.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top