giovedì 8 settembre 2011

Per indirizzare o meno percorso, questo è il problema


Quando ho scritto su Costruire una rete più sicura con ASafaWeb all'inizio della settimana, ho parlato con il processo di condividere alcune esperienze. Questo mi ha fatto andare un po 'strabico ed è una combinazione di una idiosincrasia nei routing ASP.NET e una domanda più filosofica circa l'intenzione semantica di un percorso.
La situazione era che avevo bisogno di costruire un URL sul sito ASafaWeb che conteneva l'indirizzo del sito da sottoporre a scansione e potrebbe essere accessibili tramite una richiesta HTTP GET. La ragione che voglio affrontare in questo modo è così che questo URL può essere passato intorno alla maniera di "Hey, guardate il risultato della scansione Ho appena ricevuto" e tutte le informazioni necessarie per eseguire una scansione identico è incapsulata all'interno dell'indirizzo.

Piano "A"

Piano "A" è stato quello di includere l'URL di un parametro di percorso in modo che una scansione per troyhunt.com sarebbe simile a questa:
http://asafaweb.com/scan/troyhunt.com
E 'tutto molto bello ed è facilmente raggiungibile mediante la registrazione di un percorso come questo:
routes.MapRoute ( "Scan" , "Scan / url * {}" , nuovo controller = { "Scan" , 
action = "Indice" });
Questo passa felicemente fuori e al ScanController esegue l'azione Index, che effettua la scansione in questo modo:
/ /
/ / GET: / scansione / asafaweb.com

pubblico ActionResult Index ( string url)
{
  / / Avvia scansione roba ...
Ma cosa succede se l'URL da sottoporre a scansione è stata sotto la radice del dominio? Che cosa succede se sembrava così:
http://asafaweb.com/scan/troyhunt.com/Search
Beh, questo va bene perché il modello URL include un jolly per tutto dopo il "" Scan / "percorso, per questo c'è una stella in" {* url} "Ma si comincia a introdurre un problema semantico, in quanto la barra nell'URL. è implicando struttura quando in realtà è solo una parte del parametro . Diamo tenere fuori sulla filosofia per ora e torneremo ad esso in un po '.
Che ne dici di questo modello:
http://asafaweb.com/scan/troyhunt.com/Search # risultato1
Ora abbiamo un vero problema perché l'hash è che implica un identificatore di frammento e viene trattato come un carattere speciale nell'URL. Quando il controller legge in quel parametro "url", l'hash e tutto ciò dopo che è stato omesso. Chiaramente il parametro percorso deve essere codificati dell'URL così invece di quello che vedete qui sopra, finisce per apparire più simile a questa:
http://asafaweb.com/scan/troyhunt.com% 2fSearch 23result1%
A destra, in modo che ottiene oltre questo ostacolo. Fino ad ora, ho barato un po 'e non tra cui il protocollo nella URL da scansionare. Di cadere "http://" mantiene tutta la cosa più succinto ed è quasi sempre implicita, dove non specificato comunque. Che cosa accade quando si tratta di un indirizzo HTTPS? Applicando lo stesso principio di codifica URL otterremo questo:
http://asafaweb.com/scan/https% 3A% 2F% 2ftroyhunt.com 2fSearch%% 23result1
Ed è qui che tutto comincia ad andare veramente male:
Percorso codificate causando un HTTP 400 a Casini
Ah merda. Ora abbiamo un problema del tutto nuovo perché il carattere ":" (codificato come 3a%), è un altro carattere speciale ed è l'aspetto sta provocando un HTTP 400 "Richiesta non valida" anche se è codificato. Ma succede solo quando si esegue direttamente da Visual Studio tramite F5 (Casini, ovviamente, giocare un ruolo qui).
Ma spesso prova direttamente contro la mia istanza locale di IIS quindi vediamo cosa succede là:
Percorso codificate causando un URL non valido in IIS
Ok, potenzialmente alcuni convalida manca più a monte in modo da tracciare il valore di URL che è passato nel controller di scansione:
https:/troyhunt.com/Search # risultato1
Vedere il problema? Il doppio slash prima che il dominio è stato trattato come un modello di fuga e ha deliberato di solo una singola barra. Ugh.
Ma aspettate - c'è di peggio! Finora ho solo mostrato cosa succede quando l'URL viene immesso direttamente nella barra degli indirizzi. Ovviamente questo non accadrà nel sistema di vivere e invece si tratterà di entrare in un URL in una casella di testo che quindi richiede la scansione pagina passando l'indirizzo in una richiesta HTTP GET. Per ora, questa casella di testo si trova solo in home page, che è collegato a un modello di vista con un attributo chiamato "ScanUrl" e un'azione in questo modo:
[ HttpPost ]
 pubblici ActionResult Index ( ScanRequestViewModel modello)
{
  se (ModelState.IsValid)
  {
    ritorno RedirectToRoute ( "Scan" , nuovo {url = model.ScanUrl});
Questo sembra ok e le mappe delle rotte nome ordinatamente al percorso che ho creato in precedenza. Vediamo ora cercare di passaggio che lo scorso URL - l'HTTPS uno con l'hash - per l'azione di cui sopra:
RedirectToRoute causando un HTTP 400
Vedi qualcosa di strano? Diverso messaggio di errore del freakin grande '? L'URL ha codificato i due punti e simboli hash, ma non la slash. In realtà, le due barre prima del dominio sono stati escape in uno nuovo, ma quello dopo il dominio è ancora vivo e vegeto. Come può essere? Non è RedirectToRoute lo scopo di codificare i valori URL percorso ?
Mi girai di Stack Overflow e le chiese perché RedirectToRoute è doppio che codifica per la "/" nei parametri che sono gli URL nel routeValues ​​. Ho ricevuto una grande risposta da David Duffett che si riduce al fatto che il reindirizzamento non è la codifica , è fuga . Ora questo è sia strano e importante perché il risultato finale è che un valore di percorso con una barra semplicemente non può essere correttamente codificato in un modo che è adatto per passare intorno a via un URL. E non pensate neppure di tentare di codificare prima di colpire RedirectToRoute perché mentre la vostra barra sarà successo codificati in% 2f, il redirect sarà quindi codificare il segno di percentuale così si finisce con doppia codifica. Non abbastanza.

Piano "B"

Senza implicare che ho semplicemente dato sul modello di percorso (! Questo è vero solo in parte), ho deciso di correre con il piano "B" - il vecchio stringa di query fidato. Questo risulta che l'ultimo indirizzo con il lotto in qualcosa di più in questo modo:
http://asafaweb.com/scan?url=https% 3A% 2F% 2ftroyhunt.com 2fSearch%% 23result1
Complessità saggio all'interno di MVC, questo è un po ' come proposta semplice non c'è rotta personalizzata, ma ancora più importante, funziona! Questo frammento di codice scorso che è stato il reindirizzamento a un percorso ora è il reindirizzamento ad una azione:
ritorno RedirectToAction ( "Indice" , "Scan" , nuovo URL = model.ScanUrl {});
Non manca slash codifica, non sfugge o doppia codifica, lo fa proprio quello che ci si aspetta.
È vero che sto scrivendo questo stanco e come ho detto prima, la cosa codifica tutto mi ha fatto un po 'strabico oltre l'ultimo giorno e un po' così ho potuto anche mancare qualcosa di ovvio. Ma da dove stoseduto stravaccato in un sonno vicino, i parametri URL semplicemente non gioca sempre pulito con percorsi.

È un URL di un parametro percorso anti-modello?

Fammi capire un po 'filosofico per un momento - è un URL di un percorso anti-modello? Voglio dire si dovrebbe mai avere un percorso che include un parametro che è un altro URL? L'intera idea di instradamento è quello di presentare un indirizzo facile da usare, che implica una certa semantica sulla risorsa è l'accesso o l'azione è spettacolo; fa un parametro potenzialmente lungo percorso pieno di caratteri di escape davvero fare questo?
Indipendentemente dall'implementazione sfide di cui sopra, c'è qualcosa su un URL come questo che si sente solo, beh, un po 'sbagliato:
http://asafaweb.com/scan/https% 3A% 2F% 2ftroyhunt.com 2fSearch%% 23result1
È solo a me? Oppure è un URL totalmente fuori posto in una via?


Corso Visual Studio - Corsi Visual Studio
Corso .Net- Corso Dot.Net - Corso Vb.net
Corso C# - Corso PHP - Corso Joomla

Nessun commento:

Posta un commento