2017-10-25 29 views
0

私はMechanicalSoupを使用してPython 3.6経由でWebサイトにログインしていますが、CSRFトークンに問題があります。Python Web-Scraping CSRFトークンの問題

私はhtmlを要求するたびに、「無効なCSRFトークン:禁止」と読みます。ログインページのhtmlを検索すると、トークンのように見える要素IDに最も近いものは、既にトークンで埋められているように見える "autheticity_token"です。

"re"モジュールを使用してトークンを抽出し、上で話したidの要素に再発行することはできましたが、運はありませんでした。注意すべき点は、名前が与えられていないので、idで要素を見つけなければならなかったことです(これが私のRobobrowserのやり方がうまくいかなかった理由です)。

これは私がCSRFへの対応を考える要素である:私は "== B + CSP/9zR/a1yfuPPIYJSiR0v8jJUTaJaGqJmJPmLmivSn4GtLgvek0nyPvcJ0aOgeo0coHpl94MuH/r1OK5UA" この場合には、抽出し、その要素

にそれを再提出でしょう

<input id="authenticity_token" type="hidden" value="b+csp/9zR/a1yfuPPIYJSiR0v8jJUTaJaGqJmJPmLmivSn4GtLgvek0nyPvcJ0aOgeo0coHpl94MuH/r1OK5UA=="> 

ここで

が通過、ユーザーのためのダミーの値を持つ私のコードで、URL

import mechanicalsoup 
import re 

def return_token(str1): 
    match1 = "authenticity_token" 
    match2 = ".*value\=\"(.*)\".*" 
    for x in range(len(str1)): 
     line = str1[x] 
     if re.findall(match1,line): 
      token = re.findall(match2,line)[0] 
      return token 

url1 = "" 
username = "" 
password = "" 

browser = mechanicalsoup.Browser() 
page = browser.get(url1) 
str0 = page.text 
token = return_token(str0.split('\n')) 
#print(str0) 
form = page.soup.find("form",{"id":"loginForm"}) 

form.find('input', {'name': 'username'})['value'] = username 
form.find('input', {'name': 'password'})['value'] = password 
form.find('input', {'id': 'authenticity_token'})['value'] = str(token) 

response = browser.submit(form, page.url) 
print(response.text) 
+0

を - あなたは 'token'を見て、それが正しいですチェックしようとしています。また、そのアプローチを使用する代わりに、フォームから値を取得するライブラリのサポートはありませんか? –

+0

@JonClements Regexは動作しますが、それは問題ではなく、ちょうど良い値の引用符の中の値を抽出します。私はrobobrowserを使うことができません。なぜなら、フォームを取得し、要素の名前で値を入力できるからです(これには名前はなく、省略されています)。 – JCodder

+0

それは、それが見つけることができる次の見積もりにすべてを抽出するように見えますが、最も即時のものではありません... –

答えて

1

私はここでの問題は、その<input>であると信じて要素にPOSTまたはGETを介してサブミットするための属性がnameである必要があります。あなたのトークンはname-<input>の要素になっているので、MechanicalSoupによって処理されません。なぜなら、それはブラウザが行うことなのですから。 W3C specificationから

成功するたびにコントロールが送信されたフォームデータセットの一部として、現在の値とペアのコントロール名を持っています。成功した制御は、FORM要素内で定義され、制御名を持たなければなりません。

...

コントロールの「コントロール名」は、そのname属性によって指定されます。

おそらく、CSRFトークンを処理しているJavaScriptがあります。同様の議論については

MechanicalSoupの使用状況についてDoes form data still transfer if the input tag has no name?


を参照して、クラスStatefulBrowserFormは、スクリプトを簡素化します。たとえば、あなただけのユーザー名とパスワードページを開くために持っていたし、入力した場合:正規表現はそれのルックスによって、間違っていると

import mechanicalsoup 

# These values are filled by the user 
url = "" 
username = "" 
password = "" 

# Open the page 
browser = mechanicalsoup.StatefulBrowser(raise_on_404=True) 
browser.open(url) 

# Fill in the form values 
form = browser.select_form('form[id=loginForm]') 
form['username'] = username 
form['password'] = password 

# Submit the form and print the resulting page text 
response = browser.submit_selected() 
print(response.text)