2012-05-01 17 views
6

Io uso Django e ckeditor per fornire gusto WYSIWYG per TextEdits. Vorrei usare la funzione di caricamento file di CKEditor (nella finestra di dialogo filebrowser/immagine), ma il POST realizzato da CKEditor per caricare l'immagine contiene solo i dati del file.Come aggiungere un campo per POST valori in CKEditor caricare

Questo è un problema per il controllo CSRF. Non sono riuscito a trovare la documentazione di CKEditor e a trovare un posto a modificare i dati POST per il caricamento di file, per aggiungere il csrf_token di django nei dati POST.

Come soluzione temporanea, posso modificare i parametri filebrowserUploadUrl per includere i dati csrf nell'URL di caricamento, utilizzare @csrf_exempt per la vista di caricamento e controllare i parametri request.GET per controllare csrf. Ma questa soluzione è sicura?

In ogni caso, se qualcuno sa come includere CSRF gettone direttamente all'interno CKEditor dati upload di file POST, io sono fortemente interessati ...

+0

Stai utilizzando [django-ckeditor] (http://pypi.python.org/pypi/django-ckeditor) o un altro widget? Se lo stai scrivendo da solo: è corretto, non puoi aggiungere qualcosa al POST perché il corpo pubblicato è il file stesso. Quindi sì, è necessario fornire un token nei parametri dell'URL. – ilvar

+0

anche django-ckeditor non usa protezione CSRF per il caricamento di file (e questo è male IMHO): @csrf_exempt def caricare (richiesta): """ carica un file e inviarlo di nuovo l'URL di CKEditor TODO:. Convalida i caricamenti "" " – jmbarbier

risposta

5

È possibile registrarsi per l'evento dialogDefinition, e riscrivere completamente la scheda di upload, quindi:

CKEDITOR.on('dialogDefinition', function (ev) { 
    var dialogName = ev.data.name; 
    var dialogDefinition = ev.data.definition; 
    if (dialogName == 'image') { 
    dialogDefinition.removeContents('Upload'); 
    dialogDefinition.addContents({ 
     title: "Upload", 
     id: "upload", 
     label: "Upload", 
     elements: [{ 
     type: "html", 
     html: '<form><input id="imageupload" type="file" name="files[]" />{%csrf_token%}</form>' 
     }] 
    }); 
    } 
}); 

Questa è una testata semplificazione della mia versione del mondo reale, ma si spera che mostri l'idea.

Questo non imposta il campo URL nella finestra di dialogo immagine, quindi facendo clic su OK nella finestra di dialogo verrà visualizzato un messaggio di errore. Sarà necessario impostare che in un caricamento riuscito, quindi:

CKEDITOR.dialog.getCurrent().getContentElement('info', 'txtUrl').setValue(theURL); 
+1

Wow, nuova risposta alla vecchia domanda :-) grazie !! ... il tuo modo è molto più pulito del mio hacking nel codice del ckeditor. Proverò la tua strada la prossima volta dovrò usare il ckeditor. – jmbarbier

+0

Ricevo: "Uncaught TypeError: Impossibile leggere la proprietà 'getContentElement' di null" Cosa mi manca? – Mladen

1

Sembra che non v'è alcun modo per aggiungere i dati ai dati di upload ckeditor senza editing codice sorgente ckeditor. Il codice sorgente da modificare è plugins/dialogui/plugin.js, attorno alle righe 1440 in ckeditor 3.6.2, dove ckeditor crea il modulo utilizzato dall'iframe di upload.

// ADDED TO CKEDITOR CODE %< 
var csrfitems = document.getElementsByName("csrfmiddlewaretoken") 
var csrftoken = "" 
if(csrfitems.length > 0) 
    csrftoken = csrfitems[0].value 
// >% END OF ADDED CODE 
if (elementDefinition.size) 
    size = elementDefinition.size - (CKEDITOR.env.ie ? 7 : 0); // "Browse" button is bigger in IE. 
frameDocument.$.write([ '<html dir="' + langDir + '" lang="' + langCode + '"><head><title></title></head><body style="margin: 0; overflow: hidden; background: transparent;">', 
'<form enctype="multipart/form-data" method="POST" dir="' + langDir + '" lang="' + langCode + '" action="', 
CKEDITOR.tools.htmlEncode(elementDefinition.action), 
'">', 
// ADDED TO CKEDITOR CODE 
    '<input type="hidden" name="csrfmiddlewaretoken" value="',csrftoken,'"/>', 
    // >% END OF ADDED CODE 
'<input type="file" name="', 
CKEDITOR.tools.htmlEncode(elementDefinition.id || 'cke_upload'), 
'" size="', 
CKEDITOR.tools.htmlEncode(size > 0 ? size : ""), 
'" />', 
'</form>', 

E ora possiamo tranquillamente utilizzare caricare in ckeditor con Django

2

I dati aggiuntivi inviati al server viene passato su richiesta get. Stavo cercando di aggiungere dati in più e, infine, raggiungere questo obiettivo aggiungendo una parametri URL del modulo che viene utilizzato per inviare i dati

CKEDITOR.on('dialogDefinition', function(ev) 
    { 
    var dialogName = ev.data.name; 
    var dialogDefinition = ev.data.definition; 
    if (dialogName == 'image') 
    { 
      dialogDefinition.contents[2].elements[0].action += '&pin=123456'; 
      /* 2 is the upload tab it have two elements 0=apparently is the 
      and 1: is the button to perform the upload, in 0 have the action property with the parameters of the get request simply adding the new data    
       */ 

    } 
    }); 
1

ho sperimentato un problema simile quando l'integrazione di caricamento delle immagini attraverso CKEditor per Elgg. La soluzione meno intrusiva mi è venuta è stato quello di legare l'evento OnClick per il pulsante di invio e modificare la forma direttamente da questo:

CKEDITOR.on('dialogDefinition', function (ev) { 
    var dialogName = ev.data.name; 
    var dialogDefinition = ev.data.definition; 

    if (dialogName === 'image') { 
     var uploadTab = dialogDefinition.getContents('Upload'); 

     for (var i = 0; i < uploadTab.elements.length; i++) { 
      var el = uploadTab.elements[i]; 

      if (el.type !== 'fileButton') { 
       continue; 
      } 

      // add onClick for submit button to add inputs or rewrite the URL 
      var onClick = el.onclick; 

      el.onClick = function(evt) { 
       var dialog = this.getDialog(); 
       var fb = dialog.getContentElement(this['for'][0], this['for'][1]); 
       var action = fb.getAction(); 
       var editor = dialog.getParentEditor(); 
       editor._.filebrowserSe = this; 

       // if using jQuery 
       $(fb.getInputElement().getParent().$).append('<input type="hidden" name="foo" value="bar">'); 

       // modifying the URL 
       fb.getInputElement().getParent().$.action = '/my/new/action?with&query&params=1'; 


       if (onClick && onClick.call(evt.sender, evt) === false) { 
         return false; 
       } 

       return true; 
      }; 
     } 
    } 
}); 
1

La domanda è troppo vecchio, ma ...

Versione 4.5 si può aggiungere il gancio in qualsiasi richiesta

editor.on('fileUploadRequest', function(evt) { 
    var xhr = evt.data.fileLoader.xhr; 

    xhr.setRequestHeader('Cache-Control', 'no-cache'); 
    xhr.setRequestHeader('csrf header ', 'HEADER'); 
    xhr.withCredentials = true; 
}); 
+0

Non funziona con il caricamento predefinito di FileBrowser: http://stackoverflow.com/questions/34851158/ckeditor-4-5-fileuploadrequest-event-not-firing –

0

Fornendo si sta inviando un gettone CSFR nell'URL attraverso HTTPS dovrebbe essere ok per farlo (da una pinta di vista della sicurezza) e anche molto più facile da affrontare.

Ciò presuppone che django possa leggere quella variabile o che tu sia in grado di modificare facilmente django. Queste risposte che provano ad alterare CKeditor sembrano un po 'troppe cose da fare.

Fintanto che il tuo CSFR_token viene inviato dal browser degli utenti in modo sicuro al server, non importa se è tramite POST o GET. La preoccupazione per la sicurezza in gioco è un attacco uomo centrale, ovvero non si desidera che un CSFR_token dell'utente venga trasmesso in chiaro.

In senso stretto, questo tipo di dati deve essere inviato come POST in base alle specifiche HTTP, ma questa sembra una situazione in cui 'uso improprio' del protocollo GET potrebbe essere accettabile in quanto non si ha il controllo del codice CKEditor in un particolare modo elegante.

Inoltre, CKEditor può cambiare le cose in un aggiornamento, passando il token tramite l'URL funzionerà sempre.

Problemi correlati