2015-07-24 5 views
5

J'utilise Python 3 pour un script qui surveille les mises à jour du profil d'un utilisateur sur une page Web. La connexion à ce site est protégée par des contre-mesures CSRF, ce qui est une bonne chose. Cependant, je ne peux pas obtenir mon script pour me connecter à ce site.Connectez-vous à un site Web via Python - comment faire face à CSRF?

  • Mon approche à l'aide 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)) 
    
  • Mon approche à l'aide 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)) 
    

Dans les deux cas, je finis avec un état HTTP 403 et un message dire CSRF verification failed. Request aborted.

  • Des idées pour résoudre ce problème?
  • Le formulaire en question a une entrée masquée contenant un jeton CSRF. Je suppose que mechanicalsoup et robobrowser soumettra également cette entrée. Ai-je raison? Ou dois-je le traiter spécialement?
  • Je pensais que la session utilisée par ces deux paquets gérerait tout comme les cookies et ainsi de suite. Y a-t-il quelque chose que j'ai manqué?

Répondre

6

J'ai obtenu la variante robobrowser pour travailler en définissant l'en-tête Referer.

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

Ainsi, le code complet qui a fonctionné pour moi est la suivante:

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

Merci, ça marche pour moi. – guoqiao

0

Vous ajoutez uniquement un nom d'utilisateur et un mot de passe au formulaire que vous soumettez, vous devez également ajouter le champ de jeton csrf. Voir ci-dessous, je suppose que vous pouvez comprendre le nom du champ et la valeur du jeton.

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

La valeur symbolique sera différente pour chaque soumission de formulaire, de sorte que vous devrez obtenir le formulaire et analyser la valeur jeton CSRF et le soumettre avant l'expiration du délai pour le jeton.

+0

Le CSRF est déjà sous la forme. L'ajouter manuellement au formulaire ne modifie pas le comportement. Encore 403. – Scolytus

+0

Pouvez-vous parcourir et imprimer les valeurs dans la forme juste avant cela: 'browser.submit_form (form)'? – mikeb

+0

Merci pour l'effort, mais le problème était l'en-tête 'Referer' manquant. J'ai vérifié l'objet de formulaire comme vous l'avez suggéré, mais il y avait tout dedans. Il semble que ce soit un comportement particulier de cette application Web particulière, car je ne vois pas pourquoi le référant serait nécessaire. – Scolytus