curlでDropboxにアクセスする試み

curlというコマンドがある。引数にURLを指定すると、そこにアクセスして、サーバーから情報を取得するのだ。

基本

  • 基本の書式。
$ curl http://d.hatena.ne.jp/zariganitosh
...(非常に長いhtml出力)...
  • ズラズラとhtmlが出力されたが、htmlの羅列では訳が分からん。
  • htmlファイルに出力してみる。
$ curl -o output.html http://d.hatena.ne.jp/zariganitosh/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4178  100  4178    0     0  12717      0 --:--:-- --:--:-- --:--:-- 22830
  • output.htmlをブラウザで開くと、お馴染みの「ザリガニが見ていた...。」のページが表示された!
  • URLを確認すると、しっかりfile://で始まっている。
  • curlが保存したoutput.htmlが表示されている証拠!

Basic認証

  • ところで、世の中には認証が必要なページもある。(素晴らしいBasic認証のサンプルページに感謝です!


Basic認証の見本ページ
ID = [guest] PASS = [1234] で入る事ができます。

Basic認証・パスワード制限
  • curlで基本どおりにアクセスしても、401エラーで拒否されてしまう。
$ curl http://kensakuyoke.web.fc2.com/basic-test/test.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<title>401 Authorization Required</title>
</head><body>
<h1>Authorization Required<:/h1>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
</body></html>
  • しかし、curlに死角はない。
  • -uオプションで'ユーザー名:パスワード'を指定すればいいのだ!
$ curl -u 'guest:1234' http://kensakuyoke.web.fc2.com/basic-test/test.html

Twitterへのアクセス

  • では、Twitterにアクセスするにはどうすればいいのだろうか?
  • 現在のTwitterBasic認証が廃止されているので、-uオプションでは無理。
  • 試行錯誤の結果、以下の書式で認証を通ってアクセスできた。
$ curl -L -v -c cookie.txt -o output.html --data-urlencode 'session[username_or_email]=EMAIL_ADRESS' --data-urlencode 'session[password]=PASSWORD' https://twitter.com/sessions
      • EMAIL_ADRESS・PASSWORDは、自分のTwitter認証用のメールアドレス・パスワードに置き換える。
  • -Lオプション = リダイレクトしたら、リダイレクト先の情報を取得する。
  • -vオプション = サーバーとのやり取りを詳細に出力する。(指定しなくてもOK)
  • -c cookie.txt = クッキーをcookie.txtファイルに保存する。
  • --data-urlencode 'データ文字列' = urlエンコードしたデータ文字列をPOST送信する。
  • そして、一旦認証されてクッキーを取得できれば、以降はクッキーを手土産にアクセスを許可してくれる。
$ curl -L -v -b cookie.txt -o output.html https://twitter.com/home
  • -b cookie.txt = クッキーを手土産にアクセスする。

Dropboxへのアクセス

  • Twitterと同じ仕組みでDropboxにもアクセスできるのかと思いきや、できなかった...。
  • 更なる試行錯誤を重ねて、ようやく以下の手順でアクセスできるようになった。
  • まず、Dropboxのログインページにアクセスする。
  • その際クッキーを貰ったら保存するようにしておく。
$ curl -L -c cookie.txt -o output.html https://www.dropbox.com/login
  • そして、返されたoutput.htmlページから、セキュリティートークン(CSRF対策?)を抜き出す。
$ cat output.html|grep -e '^lt;input type="hidden" name="t" value=".*" />'
<input type="hidden" name="t" value="rwCnACsd0rAQPVszUTL6cj-7" />
  • そして、クッキーを手土産に(-b cookie.txt)、以下のデータをPOST送信するのだ。

上記のセキュリティートーク --data-urlencode 't=rwCnACsd0rAQPVszUTL6cj-7'
メールアドレス --data-urlencode 'login_email=EMAIL_ADRESS'
パスワード --data-urlencode 'login_password=PASSWORD'

  • さらに、認証時に貰うクッキーも、忘れずに保存しておく。
$ curl -L -b cookie.txt -c login_cookie.txt -o output.html --data-urlencode 't=rwCnACsd0rAQPVszUTL6cj-6' --data-urlencode 'login_email=EMAIL_ADRESS' --data-urlencode 'login_password=PASSWORD' https://www.dropbox.com/login
      • EMAIL_ADRESS・PASSWORDは、自分のDropbox認証用のメールアドレス・パスワードに置き換える。
  • 無事認証されてクッキーを貰えれば、次回以降はlogin_cookie.txtを手土産に、アクセス可能になるのだ!
$ curl -L -b login_cookie.txt -o output.html https://www.dropbox.com/home
$ curl -L -b login_cookie.txt -o output.html https://www.dropbox.com/revisions/hello.txt


長い道のりであった!

  • Webブラウザでは、上記の手順を裏で賢く処理してくれるのだけど、
  • curlを使うときは、すべて自分で手順どおりに実行する必要があるのだ。

一連のスクリプト

#!/bin/bash

EMAIL_ADRESS=$1
PASSWORD=$2
FILE_NAME=$3

curl -L -c cookie.txt -o output.html https://www.dropbox.com/login
TOKEN=`cat output.html | grep -e '<input type="hidden" name="t" value=".*" />' | grep -o 'value=".*"' | grep -o '".*"' | grep -o '[^"].*[^"]'`
curl -L -b cookie.txt -c login_cookie.txt -o output.html \
     --data-urlencode "t=$TOKEN" \
     --data-urlencode "login_email=$EMAIL_ADRESS" \
     --data-urlencode "login_password=$PASSWORD" \
     https://www.dropbox.com/login
curl -L -b login_cookie.txt -o output.html "https://www.dropbox.com/revisions/$FILE_NAME"
  • 実行権限を付与して、
$ chmod a+x dropbox_curl.sh
  • 実行してみる。
$ dropbox_curl.sh メールアドレス パスワード ファイル名
      • ファイル名は、Dropboxをルートとするパス名。
      • 例:~/Dropbox/hello.txt → hello.txt
      • 例:~/Dropbox/folder/hello.txt → folder/hello.txt
  • ブラウザでoutput.htmlを確認してみる。

できた!

疑問

  • ところで、何でTwitterはセキュリティートークンを送信しなくても認証できてしまったんだろう?
  • 見直してみると、Twitterのログインページにも、しっかりセキュリティートークンが準備されているのに...。
<input type="hidden" value="b3097c73d2ec54ca5fcb7b1d3be96d9c2064799f" name="authenticity_token"/>

謎。