2015-07-24 17 views
5

Sto usando Python 3 per uno script che monitorerà gli aggiornamenti nel profilo di un utente su una pagina web. L'accesso a questo sito è protetto dalle contromisure CSRF, che è una buona cosa. Tuttavia, non riesco a ottenere il mio script per accedere a questo sito.Accesso a un sito Web tramite Python: come gestire CSRF?

  • Il mio approccio con mechanicalsoup:

    import mechanicalsoup 
    
    browser = mechanicalsoup.Browser() 
    login_page = browser.get(base_url) 
    login_form = login_page.soup.select(".form-signin")[0] 
    
    login_form.find(attrs={"name": "username"})['value'] = 'username' 
    login_form.find(attrs={"name": "password"})['value'] = 'password' 
    
    page2 = browser.submit(login_form, login_url) 
    print(str(page2.text)) 
    
  • Il mio approccio con robobrowser:

    import re 
    from robobrowser import RoboBrowser 
    
    browser = RoboBrowser(history=True) 
    browser.open(base_url) 
    form = browser.get_form(action='/login/') 
    
    form["username"] = 'username' 
    form["password"] = 'password' 
    
    browser.submit_form(form) 
    print(str(browser.select)) 
    

In entrambi i casi io alla fine con uno stato HTTP 403 e un messaggio dicendo CSRF verification failed. Request aborted.

  • Qualche idea su come risolvere questo problema?
  • Il modulo in questione ha un input nascosto contenente un token CSRF. Credo che mechanicalsoup e robobrowser invieranno anche questo input. Ho ragione? O devo trattarlo in modo speciale?
  • Pensavo che la sessione utilizzata da questi due pacchetti gestisse tutto come i cookie e così via. C'è qualcosa che ho perso?

risposta

6

Ho ottenuto la variante robobrowser impostando l'intestazione Referer.

browser.session.headers['Referer'] = base_url 

Quindi il codice completo che ha lavorato per me è la seguente:

import re 
from robobrowser import RoboBrowser 

browser = RoboBrowser(history=True) 
browser.open(base_url) 
form = browser.get_form(action='/login/') 

form["username"] = 'username' 
form["password"] = 'password' 
browser.session.headers['Referer'] = base_url 

browser.submit_form(form) 
print(str(browser.select)) 
+0

Grazie, lavora per me. – guoqiao

0

Si sta aggiungendo solo il nome utente e la password al modulo che si sta inviando, è necessario aggiungere anche il campo token csrf. Vedi sotto, suppongo che tu possa capire il nome del campo e il valore del token.

form["username"] = 'username' 
form["password"] = 'password' 
form["csrffieldname"] = 'csrfvalue' # This is what you are missing 

Il valore del token sarà diverso per ogni invio del modulo, in modo da avere per ottenere la forma e analizzare il valore token CSRF e presentarlo prima del timeout per il token.

+0

Il CSRF è già in forma. L'aggiunta manuale al modulo non modifica il comportamento. Ancora 403. – Scolytus

+0

Si può scorrere e stampare i valori nel modulo subito prima: 'browser.submit_form (form)'? – mikeb

+0

Grazie per l'impegno, ma il problema era l'intestazione "Referer" mancante. Ho controllato l'oggetto del modulo come suggerito, ma aveva tutto ciò che conteneva. Sembra che questo sia un comportamento speciale di questa particolare app Web, dal momento che non riesco a capire perché il referrer sarebbe necessario. – Scolytus

Problemi correlati