2010-01-14 20 views
11

Internet Explorer (con le impostazioni predefinite, che presumo in genere saranno effettive sui desktop di Great Unwashed) sembra non gradire l'idea di accettare il contenuto degli allegati in una risposta HTTP se la richiesta corrispondente non è stata effettuata direttamente da un utente azione (come un gestore di "clic" o un modulo nativo invia). Probabilmente ci sono più dettagli e sfumature, ma questo è il comportamento di base che mi sta frustrando.Quali sono le tecniche per aggirare le regole di sicurezza del download del file IE?

Mi sembra che questa situazione sia comune: l'interfaccia utente di fronte a qualche contenuto scaricabile — dice, un report PDF preparato — consente di utilizzare alcune opzioni e input per la creazione del contenuto. Ora, come con tutti i moduli che consentono all'utente di stabilire come un'applicazione fa qualcosa, è possibile che l'input sia errato. Non sempre, ma a volte.

Quindi c'è un dilemma. Se il client cerca di fare qualcosa di stravagante, come eseguire una transazione AJAX per consentire al server di controllare i contenuti del modulo, e quindi inviare nuovamente per ottenere il download, a IE non piacerà. Non piacerà perché la transazione HTTP effettiva che riporta l'allegato non avverrà nel gestore di eventi azione dell'utente originale, ma nel callback del completamento AJAX. Peggio ancora, dal momento che la barra di sicurezza di IE sembra pensare che la soluzione a tutti i problemi è semplicemente ricaricare la pagina esterna dal suo URL originale, il suo invito all'utente a procedere e scaricare i contenuti sospetti non funzionerà nemmeno.

L'altra opzione è quella di far sparire il modulo. Il server controlla i parametri e, se c'è qualcosa di sbagliato, risponde con la pagina del contenitore di moduli, in modo appropriato con i messaggi di errore. Se il contenuto del modulo è OK, genera il contenuto e lo invia nuovamente nella risposta HTTP come file allegato. In questo caso (penso), IE è felice perché il contenuto è stato apparentemente richiesto direttamente dall'utente (che è, tra l'altro, un modo ridicolmente fragile per raccontare buoni contenuti da contenuti non validi). Questo è grandioso, ma il problema ora è che l'ambiente client (cioè il codice sulla mia pagina) non può dire che il download ha funzionato, quindi il modulo è ancora solo seduto lì. Se il mio modulo è in una sorta di finestra di dialogo, allora ho davvero bisogno di chiuderlo quando l'operazione è completa — in realtà, questa è una delle motivazioni per farlo in modo AJAX.

Mi sembra che l'unica cosa da fare sia dotare le finestre di dialogo del modulo con messaggi che dicono qualcosa come "Chiudi quando il download inizia." Questo mi sembra davvero schifo perché è un esempio di un'interfaccia "per favore premi questo pulsante per me": idealmente, il mio codice dovrebbe essere in grado di spingere il buutton quando è appropriato. Una cosa fondamentale che non conosco è se esiste un modo in cui il codice client può rilevare che l'invio del modulo ha comportato il download di un allegato. Non ho mai sentito di un modo per rilevarlo, ma ciò mi spezzerebbe l'impasse.

risposta

8

Suppongo che stai presentando il modulo con una finestra di destinazione diversa; da qui la forma rimanendo al suo posto.

Ci sono diverse opzioni.

  1. Tenere disattivato il pulsante di invio e effettuare la convalida in corso in background, interrogando il modulo per le modifiche ai campi e quindi disattivando la richiesta di convalida per un campo mentre cambia. Quando il modulo è in uno stato valido, abilitare il pulsante; quando non lo è, disabilita il pulsante. Questo non è perfetto, poiché ci sarà un ritardo, ma potrebbe essere abbastanza buono per qualsiasi cosa tu stia facendo.
  2. Effettuare la convalida di base che non richiede round trip sul server in un gestore per l'evento submit del modulo, quindi inviare il modulo e rimuoverlo (o eventualmente nasconderlo). Se l'ulteriore convalida sul server rileva un problema, può restituire una pagina che utilizza JavaScript per dire alla finestra originale di visualizzare nuovamente il modulo.
  3. Utilizzare un cookie di sessione e un ID modulo univoco (l'ora corrente da new Date().getTime() dovrebbe essere eseguita); quando il modulo viene inviato, disabilita il pulsante di invio ma mantienilo visibile fino a quando la risposta non ritorna. Fai in modo che la risposta imposti un cookie di sessione con quell'ID che indica successo/fallimento. Fai in modo che la finestra che contiene il modulo esegua il poll per il cookie ogni secondo circa e che agisca sul risultato quando lo vede. (Non ho mai fatto quest'ultimo;. Non immediatamente vedere il motivo per cui non avrebbe funzionato)

mi ci aspetta sono circa una dozzina di altri modi per la pelle questo gatto, ma questi sono tre che è venuto a mente.

(Edit) Se non stai presentando a un target diverso, si potrebbe desiderare di andare avanti e farlo - ad una nascosta iframe sulla stessa pagina. Questo (eventualmente combinato con le risposte precedenti o altre) potrebbe aiutarti a ottenere l'esperienza utente che stai cercando.

+0

No, quando si invia un modulo e la risposta è un allegato (ovvero un file da scaricare) il browser non ridisegna la pagina. – Pointy

+0

Quest'ultima sembra davvero una buona idea! Mi chiedo se il cookie verrà impostato correttamente se il download non riesce. Idea brillante se funziona o no! – Graza

+0

@Pointy: Ah, ok, sembrava un po 'strano. Penso che queste idee di base possano essere adattate a quello che stai facendo, ma senza essere nel profondo di esso ... @Graza: È gentile. Non penso che lo definirei "brillante" se non funziona, ma grazie. :-) –

2

C'è tutta una serie di davvero buone ragioni IE fa questo, e sono sicuro che non è qualcosa che chiunque avrebbe discutere con - così l'obiettivo principale è quello di andare in giro in qualche modo per rendere le cose migliori per gli utenti.

A volte vale la pena ripensare come sono fatte le cose. Forse disabilita il pulsante, usa javascript per controllare quando tutti i campi sono compilati e spara una richiesta Ajax una volta che sono. Se l'ajax ha avuto successo, attiva il pulsante. Questo è solo un suggerimento, sono sicuro che ci saranno più ...

Edit: altro ...

Do semplice presentazione (non-AJAX), e se i controlli non riescono, inviare una pagina indietro anziché un allegato. La pagina rinviata potrebbe contenere tutte le informazioni originariamente inviate (più qualsiasi messaggio di errore per l'utente) in modo che l'utente non debba compilare di nuovo l'intero modulo. E sono anche sicuro che ci saranno più idee ...

Edit: altro ...

Sono sicuro che hai visto questo tipo di cose prima - e sì, è un extra clic (non è l'ideale, ma non è difficile) .... un "se il download fallisce, clicca qui" -> in questo caso, fallo come vuoi, ma aggiungi un nuovo link/pulsante alla pagina quando l'AJAX ritorna, quindi se il download fallisce, possono inviare il modulo già convalidato da una "azione diretta dell'utente". E sono sicuro che penserò di più (o qualcun altro lo farà) .....

+0

Beh, sono d'accordo che IE lo faccia per "buoni" motivi, ma in larga misura queste ragioni implicano che altri software di sistema non sono molto intelligenti.Tieni presente che Firefox, Safari e Chrome non presentano questo problema e, a quanto ne so, non è considerato un'esposizione di sicurezza significativa. – Pointy

1

Ho combattuto un problema simile per un po '. Nel mio caso, la pubblicazione su un iframe nascosto non ha funzionato se la mia app Web è stata incorporata in un iframe su un altro sito (problemi con cookie di terze parti) a meno che il nostro sito non sia stato aggiunto all'elenco dei siti attendibili.

Ho scoperto che è possibile suddividere il download nella sequenza POST e GET. Il post restituisce un GUID di breve durata che può essere utilizzato in una richiesta GET per avviare il download. Il POST può eseguire la convalida del modulo e restituire il GUID in una risposta corretta. Una volta che il client ha il GUID, puoi impostare la proprietà src di un elemento iframe nascosto nell'URL di download. Il browser vede l'intestazione "Content-Disposition": "attachement" e fornisce all'utente un nastro di download per scaricare il file.

Finora sembra funzionare in tutti gli ultimi browser. Sfortunatamente richiede di modificare l'API lato server per scaricare il file.

+0

Questo funziona bene, ma seriamente il "trucco dei cookie" è un modo sicuro e affidabile per far funzionare l'interazione. – Pointy

+0

@Pointy Mi piace molto il trucco con i cookie e sono sicuro che funzionerà perfettamente per te. L'ho provato, ma come ho detto, ho bisogno che i download funzionino su IE11 quando l'app web è in esecuzione su un iframe ospitato da una terza parte. La parte cookie funziona, ma IE mangerà il nastro di download se provo a pubblicare un modulo su un iframe nascosto. - Ho appena aggiunto la mia risposta nel caso qualcuno possa trovarla utile. –

+0

Sì, OK, potrebbe fare una grande differenza. Il mio sito è piuttosto vanilla. – Pointy

Problemi correlati