curlコマンドの紹介

curlコマンドの紹介ページアイキャッチ

このページでは curl コマンドの紹介をしていきます!

curl コマンドを利用することで、普段ウェブブラウザ上で行なっていた操作をコマンドで実現することが可能になります。また HTTP に関する知見も広げることができます。

動作確認では MacOSX を利用しましたが、おそらく Linux や Windows でもオプションや動作は変わらないと思いますので参考になると思います。

curl コマンド

curl コマンドはサーバーとデータを送受信するコマンドになります。

curl は Client for URL の略であり、コマンド実行した端末(PC)をクライアントとして URL で指定した端末(サーバー)に対してデータを送信し、その応答となるデータを受信するコマンドになります。

カールコマンドの説明図

curl コマンドでは単にデータの送受信を行うだけでなく、下記のようなプロトコルに従った形式のデータ&手順でのデータの送受信に対応しています。

  • HTTP
  • FTP
  • SMTP
  • SMB
  • などなど

分かりやすい例は HTTP だと思います。

ウェブページを表示する際にはウェブブラウザとウェブサーバーとの間でデータの送受信が行われますが、上手くウェブページを表示するためには送受信するデータの構造や送受信するデータの順番などが HTTP のプロトコルに従ったものでなければなりません。

例えばウェブブラウザからウェブサーバーに対して送信するデータは HTTP リクエストというデータでなければなりませんし、ウェブブラウザがウェブサーバーから受信するデータは HTTP レスポンスというデータでなければなりません。

ウェブブラウザを使用してウェブページを表示する際にはウェブブラウザが HTTP に従ったデータの送受信を行ってくれますが、curl コマンドでも同様に、プロトコルに従ったデータの送受信を行ってくれます。

具体的には、curl コマンドを実行して特定のサイトのサーバーに対して HTTP リクエストを送信し(データの送信)、サーバーからそのレスポンスとしてサイトのページを表示するための HTML を受信するようなことができます(データの受信)。

そのため、ウェブブラウザを利用しなくても、ウェブブラウザが行っているデータの送受信を curl コマンドから行うようなことが可能となります。

curlコマンドでウェブブラウザでの操作を代わりに行う様子

このページでは、ここまでも紹介した HTTP に主に焦点を当てて、curl コマンドの利用例を紹介していきたいと思います。

前述の通り、HTTP リクエストを送信するだけであれば、コマンドをわざわざ利用しなくてもウェブブラウザから実現することができます(アドレスバーに URL を指定したり、リンクをクリックしたり)。

ただ、コマンドで実現することで手順化しやすくなりますし、スクリプトなどを書いて様々なリクエストを自動で繰り返し送信するようなことも可能になります(ウェブアプリの動作確認等でも利用できますよね)。

curl コマンドでよく使うオプション

環境や curl コマンド自体のバージョン等によって異なる可能性はありますが、curl コマンドを単に実行するだけだとリクエストをサーバーに送信し(リクエストのメソッドは GET )、サーバーから受け取った HTML が標準出力に出力されるだけになります。

ただし、curl コマンドには様々なオプションが用意されており、このオプションを指定することで curl コマンドの動作を細かく制御することが可能になります。

正直私もそこまで curl コマンドに精通しているわけではないのですが、下記あたりのオプションは覚えておくと良いと思います。

  • -v (--verbose):
    • より詳細な情報を出力する(リクエストヘッダーなど)
  • -i (--include):
    • レスポンスヘッダーを含めて出力する
  • -L (--location);
    • リダイレクトを追従する
  • -d (--data);
    • POST でフォームを送信する
    • 引数で送信するコンテンツを指定する
  • -c (--cookie-jar):
    • 受信した Cookie を保存する
    • 引数には保存先のファイルパスを指定する
  • -b (--cookie):
    • Cookie をサーバーに送信する
    • 引数には送信するファイルのパス等を指定する(Cookie が記述されたファイルのパス)
  • --trace
    • 送信・受信したデータをバイナリダンプして出力する
    • 引数には出力先のファイルパスを指定する
  • -c (–user):
    • 認証時のユーザー名とパスワードを指定する

簡単にオプションの説明も記述していますが、正直これだけだと良くわからないものも多いのではないかと思います。

以降で紹介する curl コマンドの利用例では上記のオプションを指定して curl コマンドで様々な動作を実現する例を紹介しています。是非以降の解説を読んでいただき、各々のオプションの意味合いを理解していっていただければと思います。

スポンサーリンク

curl コマンドの利用例

では、続いて curl コマンドの利用例を紹介していきたいと思います。

curl コマンドで受信した HTML を出力する

まずは一番簡単な curl コマンドの利用例として curl コマンドで HTML を受信して出力する例を紹介します。

この場合は、下記のように単に curl コマンドを実行すれば良いだけです。

% curl [URL]

[URL] の部分には、受信したい HTML の URL、言い換えれば表示したいウェブページの URL を指定します。

例えば、このサイトのトップページの URL の HTML を受信して出力したいのであれば下記のようにコマンドを実行することになります。

% curl https://daeudaeu.com

コマンドを実行すると、受信した HTML が標準出力に出力されます。

もちろんコマンドのリダイレクトを利用することも可能で、下記のように実行すれば受信した HTML が標準出力ではなくカレントディレクトリの index.html というファイルに出力されることになります。

% curl https://daeudaeu.com >index.html

ちなみに、コマンドのリダイレクトに関しては下記ページで解説していますので、詳細を知りたい方は是非読んでみてください(コマンドのリダイレクトは、後述で説明するリダイレクトとは異なるものなので注意してください)。

リダイレクトの解説ページアイキャッチコマンドのリダイレクトについて解説(標準入力や標準出力の接続先を変更)

さらに、出力先のファイルである index.html をダブルクリック等で開いてやれば、受信した HTML がウェブブラウザ上にページとして表示されるはずです。

curlコマンドを介してウェブページを表示する様子

Mac の場合は下記のように open コマンドを実行することで開いてページを表示することも可能です。

% open index.html

結局ウェブブラウザが動作しているので違いが分かりにくいかもしれませんが、上記の手順で index.html を開いた場合は、ウェブブラウザが受信した HTML ではなく、curl コマンドにより既に受信していた HTML を利用してページが表示時されることになります。

このことから、ウェブブラウザを利用した時と同様のデータの送受信が curl コマンドによって実現できていることが確認できると思います。

curl コマンドでリクエストヘッダを表示する

また、curl コマンド でも解説したように、curl コマンドはサーバーにデータを送信するコマンドです(データの受信も行います)。

プロトコルが HTTP (HTTPS) の場合、クライアントは HTTP リクエストと呼ばれるデータをサーバーに送信することになります。そして、このリクエストを受け取ったサーバーから HTTP レスポンスと呼ばれるデータが送信され、クライアント(curl コマンドの場合は curl)がこのデータを受信することになります。

HTTP リクエストや HTTP レスポンスのデータの構造は下の図のようになります。例えば HTTP リクエストを送信すれば指定した URL のページを表示するための HTML を受信することができますが、その HTML は HTTP レスポンスのボディのデータとして受信されることになります。

HTTPリクエストとHTTPレスポンスのデータ構造

サーバーとクライアントの間で上の図のような構造のデータのやりとりが行われるのですが、curl コマンドをオプションなしで実行した場合、標準出力に出力されるデータは HTTP レスポンスのボディの HTML のみとなります。

もっと多くの種類のデータを出力したいような場合はオプションを指定する必要があります。例えば、HTTP リクエストのヘッダーに関しては、-v オプションを指定して curl コマンドを実行することで出力することができます。

% curl -v [URL]

-v オプションを指定することで出力結果の先頭付近に下記のように > から始まる文字列が出力されるようになります。これがサーバーに送信された HTTP リクエストのヘッダーの内容となります。

> GET / HTTP/1.1
> Host: daeudaeu.com
> User-Agent: curl/7.64.1
> Accept: */*

-v オプション自体は HTTP リクエストのヘッダーを出力することを目的としたオプションではなく、コマンドで出力される情報を詳細化するためのオプションになります。

その詳細化によって HTTP リクエストのヘッダーが出力されるようになっています。

-v オプションによって出力されるようになる情報には HTTP リクエストのヘッダーだけではなく、 HTTP レスポンスのヘッダー等も含まれます(レスポンスのヘッダーの内容は < から始まります)。

スポンサーリンク

curl コマンドでレスポンスヘッダーを表示する

特に curl コマンドでは HTTP レスポンスの方が重要であることも多いため、レスポンスのヘッダーのみを追加で出力したいような場合があります。

この場合は -i オプション(--include オプション)を指定して curl コマンドを実行します。

% curl -i [URL]

そうすると、curl コマンドの出力結果の先頭付近に下記のようにウェブサーバーの情報(Server:)や受け取る HTML のサイズ(Content-Length:)などを含むレスポンスのヘッダーも一緒に出力されるようになります。

HTTP/1.1 200 OK
Server: nginx
Date: Sun, 22 May 2022 00:54:01 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 65161
〜略〜

HTTP レスポンスの詳細のみを知りたいような場合は -v オプションよりも -i オプションの方が欲しい情報だけ出力されて結果が見やすいと思います。

curl コマンドでリダイレクト先のページを表示する

ウェブサイトにおけるリダイレクトとは、表示しようとした URL から自動的に他の URL に転送されることを言います。

例えば私のサイトであれば、http://daeudaeu.com という URL のページを表示しようとした場合、https://daeudaeu.com に自動的に転送されるようになっています(http から始まる URL から https から始まる URL に転送される)。

この例だとちょっと伝わりにくいかもしれませんが、ウェブサイトが移動した(引越しした)場合などに移動先のサイトのページに自動的に転送することを目的に利用されることが多いです。

リダイレクトの説明図

ただし、オプションなしで curl コマンドを実行した場合、リダイレクトでの転送は行われません。リダイレクトが設定された URL に curl でリクエストを送信した場合、単にその URL が移動していること及び移動先(リダイレクト先)の URL を含む HTML が受信されるだけになります。

curlコマンドでリダイレクトが行われない様子

下記がその受信する HTML の一例になります。

% curl http://daeudaeu.com   
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://daeudaeu.com/">here</a>.</p>
</body></html>

curl コマンドでリダイレクト設定されている URL にリクエストを送信した場合に自動的にリダイレクト先に転送されるようにするためには -L オプションを指定します。

% curl -L [URL]

これにより、指定した URL がリダイレクト設定されている場合は、そのリダイレクト先の URL に自動的に転送され、そのリダイレクト先の URL へのリクエストのレスポンスを受信することができるようになります。

curl コマンドで送受信したデータをバイナリ表示する

また、オプションなしで curl コマンドを実行した場合、受信した HTML のみが文字列として標準出力に出力されることになります。

それに対し、--trace オプションを指定することで、curl コマンド実行によってサーバーとの間で送受信するデータをバイナリダンプした結果をファイルに出力するようなことが可能になります。

--trace オプションの引数には出力先となるファイルのパスを指定します。

% curl [URL] --trace {ファイルのパス}

--trace オプションの引数に指定したパスのファイルには下記のように HTTP リクエストのヘッダーや HTTP レスポンスのヘッダーも含め、サーバーとの間で送受信したデータをバイナリダンプした結果が出力されることになります。

=> Send header, 82 bytes (0x52)
0000: 47 45 54 20 2f 61 70 70 2f 20 48 54 54 50 2f 31 GET /app/ HTTP/1
0010: 2e 31 0d 0a 48 6f 73 74 3a 20 6c 6f 63 61 6c 68 .1..Host: localh
0020: 6f 73 74 3a 38 30 30 30 0d 0a 55 73 65 72 2d 41 ost:8000..User-A
0030: 67 65 6e 74 3a 20 63 75 72 6c 2f 37 2e 36 34 2e gent: curl/7.64.
0040: 31 0d 0a 41 63 63 65 70 74 3a 20 2a 2f 2a 0d 0a 1..Accept: */*..
0050: 0d 0a                                           ..
<= Recv header, 17 bytes (0x11)
0000: 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
0010: 0a                                              .
<= Recv header, 37 bytes (0x25)
0000: 44 61 74 65 3a 20 4d 6f 6e 2c 20 32 33 20 4d 61 Date: Mon, 23 Ma
0010: 79 20 32 30 32 32 20 32 30 3a 34 31 3a 30 30 20 y 2022 20:41:00 
0020: 47 4d 54 0d 0a        
〜略〜

プロトコルが HTTPS の場合は送受信するデータが暗号化されることになりますが、--trace オプションでバイナリダンプされるデータは curl コマンドが送信するデータの「暗号化前のデータ」及び受信したデータの「復号化後のデータ」となります。

traceオプションで出力されるデータの説明図

なので、--trace オプションでダンプされるデータは実際に通信経路上で送受信されるパケットデータそのものでは無く、暗号化された状態のデータを出力することはできないので注意してください。

暗号化された状態のデータを表示するためには WireShark などのパケットキャプチャを行うアプリや別のコマンドを利用する必要があります。

スポンサーリンク

curl コマンドでフォームの入力&送信を行う

ここまで何度も登場してきた HTTP リクエストですが、HTTP リクエストには様々な種類のものが存在します(この種類をメソッドと呼びます)。

  • GET
  • POST
  • HEAD
  • DELETE
  • などなど

ちなみにここまで示したのは全て「メソッドを GET とする HTTP リクエスト」を送信する際の curl の使用例となります(以降、メソッドを GET とする HTTP リクエストを “GET リクエスト” と呼ばせていただきます)。

メソッドを POST とする HTTP リクエスト

ここからは「メソッドを POST とする HTTP リクエスト」を送信する際の curl の使用例についても紹介していきます(以降、メソッドを POST とする HTTP リクエストを “POST リクエスト” と呼ばせていただきます)。

GET リクエストは、主にサーバーから HTML 等のデータを要求する際に利用されます。

それに対し、POST リクエストではサーバーに対してデータを送信するようなことが可能になります。

厳密にいうと GET リクエストでもデータを送信することが可能なのですが、ここでは詳細の説明は省略させていただきます(興味のある方は「クエリパラメータ」などで検索してみてください)。

例えば皆さんも下の図のような入力フォームをウェブページ等でご覧になったことがあるのではないかと思います。

入力フォームの例

こういった入力フォームで「送信」ボタンを押せば、ウェブブラウザからサーバーに対して POST リクエストが送信されることになります。この際にフォームに入力されたデータがリクエストのボディとして送信されることになります。

そして、このデータをサーバーが受け取ってデータベースに保存することで、例えばユーザー登録などを行うことができます。

入力フォームの内容が送信される様子

この POST リクエストも curl コマンドから送信することが可能です。

つまり、ウェブブラウザ上でフォームに入力したりボタンを押したりするような操作を curl コマンドで肩代わりすることができるということです。

実際には curl コマンドではフォームへの入力やボタンの押下は行われないのですが、これらの操作が行われた時と同等のデータをサーバーに送信することが可能です。

ウェブブラウザからの入力フォーム送信時と同じデータをcurlコマンドから送信する様子

POST リクエストを送信したい場合は、curl コマンドに -d オプションを指定します。さらに -d オプションの引数として、送信したいデータを name=value の形式で指定します(name で入力フォームを指定し、value にその入力フォームへの入力値を指定)。

% curl [URL] -d name=value

例えば、ウェブブラウザで http://daeudaeu.com/page1/ の URL にアクセスすると下の図のようなウェブページが表示されるとしましょう(実際にはこんなページは無いです)。

さらに名前の入力フォームと年齢の入力フォームが1つずつ存在しており、ボタンを押すとフォームに入力されたデータが送信されるようになっているとします。

入力フォームの例

例えばここで、名前の入力フォームに daeu、年齢の入力フォームに 18 を入力した状態でボタンを押した場合に送信される POST リクエストを、curl コマンドから送信することを考えてみましょう!

前述の通り、curl コマンドを POST リクエストで送信する際には -d オプションを指定します。さらに -d オプションの引数には name=value の形式で送信するデータを指定します。

name には入力フォーム要素の name 属性の値、value にはその入力フォームに入力する値(数値や文字列)を指定します。

今回の場合は、名前の入力フォームに daeu、年齢の入力フォームに 18 を入力した場合のデータを送信することになりますので、下記のように curl コマンドを実行することになります。

% curl http://daeudaeu.com/page1/ -d 名前の入力フォームのname属性=daeu -d 年齢の入力フォームのname属性=18

あとは、名前の入力フォームのname属性年齢の入力フォームのname属性 が分かれば curl コマンドが完成することになります。

この 入力フォームのname属性 に関しては、実際に HTML を見てみるのが一番手っ取り早いと思います。

例えば Google Chrome であれば、ページを右クリックして ページのソースを表示 を選択すれば、そのページを表示する際に使用されている HTML を確認することができます。

さらに、入力フォームは input タグで生成される要素になります。上の図のような入力フォームであれば次のようなタグが存在しており、そのタグの属性の1つとして name が指定されています。この name への指定値を curl コマンドの -d オプションの引数の 入力フォームのname属性 に指定する必要があります。

入力フォームのHTML
<form action="/app/" method="post">
    <p>
        <label for="id_namae">名前:</label>
        <input type="text" name="namae" value="test" maxlength="100" required id="id_namae">
    </p>
    <p>
        <label for="id_nenrei">年齢:</label>
        <input type="number" name="nenrei" value="5" required id="id_nenrei">
    </p>
    <p><input type="submit" value="送信"></p>
</form>

で、上記の input タグにおいて、上側に表示されている名前の入力フォームは1つ目の input タグに該当しますので、name の指定値は namae であり、下側に表示されている年齢の入力フォームは2つ目の input タグに該当しますので、name の指定値は nenrei であることが分かります。

なので、名前の入力フォームに daeu、年齢の入力フォームに 18 を入力した状態でボタンを押した際に送信される POST リクエストを curl コマンドから送信する場合、下記のコマンドを実行すれば良いことになります。

% curl http://daeudaeu.com/page1/ -d namae=daeu -d nenrei=18

ただし、単に POST リクエストを送信するだけだと下記のようなエラーが発生する場合があります。

  • Cookieが設定されていない
  • 期待するトークンが設定されていない

まずは前者の Cookie について解説していきます。後者に関しては、後述の curl コマンドでフォームに設定されたトークンを送信する で解説します。

Cookie はウェブブラウザに保存される情報であり、ウェブアプリ(ウェブサイト)の「ユーザー」や「ユーザーの状態の識別」に利用されるデータ(識別子)となります。

分かりやすいのは「ユーザーがログイン中であることの識別」だと思います。

例えばウェブショッピングサイトなどであれば、ユーザーの購入履歴のページはログイン中でなければ閲覧することができませんよね?ログインせずに閲覧できてしまうと誰にでも見られてしまうことになるので困ります…。

そのようなことがないように、サーバーでは「ユーザーがログイン中であることの識別」を行い、ログイン中であれば購入履歴のページを表示し、ログイン中でなければエラーの表示やログイン画面へのリダイレクトを行うような制御が行われることが多いです。

ユーザーやユーザーの状態に応じてサーバーの動作が切り替わる様子

この制御を行うために利用されるのが Cookie です。

仕組みは簡単で、まずユーザーが入力フォームにユーザー名やパスワードを入力して送信ボタン等を押すことにより、ウェブブラウザから HTTP リクエストが送信されます。この際の HTTP リクエストのメソッドは POST となり、入力されたユーザー名やパスワードがサーバーに送信されます。

Cookieを利用した認証の流れ1

さらにサーバーは受け取ったユーザー名とパスワードから認証を行い、認証成功ならログイン後のページを表示するための HTML を HTTP レスポンスとして送信します。

この時、この HTTP レスポンスには Cookie が設定された状態で送信されます。Cookie は単なるランダム値になりますが、サーバー側で Cookie とユーザーの状態等を紐づけて管理しておくことで、その Cookie の値からユーザーの状態等を把握することができます。

Cookieを利用した認証の流れ2

さらに、HTML を受け取ったウェブブラウザは、その HTML に基づいてページの表示を行います。

そして、その後にユーザーがログイン中でなければ閲覧できないページのリンクをクリックしたような際には、ウェブブラウザから HTTP リクエストがサーバーに送信されることになります。

この時、その HTTP リクエストは先ほどサーバーから受け取った Cookie が設定された状態で送信されます。

Cookieを利用した認証の流れ3

こうすることで、サーバーは Cookie を受け取り、HTTP リクエストを送信してきたユーザーの状態を確認することができます。

そして、そのユーザーの状態がログイン中であれば、ログイン中でなければ閲覧できないページの HTML を送信し、ウェブブラウザでそのページを表示できるようにします。

Cookieを利用した認証の流れ4

HTTP リクエストに Cookie が設定されていないような場合や Cookie が不正、ログイン中でない状態の Cookie などのような場合は、ログイン中のユーザーからのリクエストでないと判断してエラーを表示するための HTML を送信したりします。

Cookieを利用した認証の流れ5

こんな感じで、Cookie を利用することでユーザーの状態等を管理することができ、これによってユーザー(クライアント)からリクエストされる URL やメソッドだけでなく、ユーザーの状態に基づいてサーバーの動作を切り替えるようなことができるようになります。

この Cookie はログイン後のページ表示だけでなく、POST リクエストによる入力フォームの送信時にも利用されることがあります。

例えば入力フォーム送信時に Cookie が設定されていなければエラーになるような場合もあります。実際 Django というウェブアプリフレームワークで作成したアプリはデフォルトでこのような制御が行われるようになっています。

ウェブブラウザから HTTP リクエストを送信したり HTTP レスポンスを受信する場合、この Cookie はウェブブラウザが自動的に保存や送信を行なってくれるので、ユーザーが Cookie の保存や送信を意識する必要はほとんどありません。

ですが、curl コマンドの場合は自動的に Cookie の保存や Cookie の送信を行なってくれませんので、curl コマンド実行時に Cookie の保存や Cookie の送信を行うことをコマンド利用者が意識する必要があります。

ただ、これらはオプションを指定するだけで簡単に実現することができます。

Cookie の保存

Cookie 自体はサーバーから勝手に HTTP レスポンスに設定されて送信されてきますので、特にオプションを指定しなくても Cookie の受信自体は行うことができます。

Coockie を受信している様子は、前述の --trace オプションにより確認することが可能です。

HTTP レスポンスのヘッダーの Set-Cookie: csrftoken= 以降の文字列が Cookie となります(実行するたびに Cookie は変化すると思います)。

<= Recv header, 168 bytes (0xa8)
0000: 53 65 74 2d 43 6f 6f 6b 69 65 3a 20 20 63 73 72 Set-Cookie:  csr
0010: 66 74 6f 6b 65 6e 3d 36 75 51 4c 66 4e 4f 44 65 ftoken=6uQLfNODe
0020: 71 49 46 4b 54 49 4b 41 66 6b 47 64 36 31 36 71 qIFKTIKAfkGd616q
0030: 6a 33 61 65 36 49 4e 65 73 74 31 72 5a 36 6e 53 j3ae6INest1rZ6nS
0040: 39 57 34 67 30 74 30 70 54 4e 44 51 4c 68 65 69 9W4g0t0pTNDQLhei
0050: 53 57 66 77 62 54 77 3b 20 65 78 70 69 72 65 73 SWfwbTw; expires
0060: 3d 4d 6f 6e 2c 20 32 32 20 4d 61 79 20 32 30 32 =Mon, 22 May 202
0070: 33 20 32 32 3a 33 35 3a 31 30 20 47 4d 54 3b 20 3 22:35:10 GMT; 
0080: 4d 61 78 2d 41 67 65 3d 33 31 34 34 39 36 30 30 Max-Age=31449600
0090: 3b 20 50 61 74 68 3d 2f 3b 20 53 61 6d 65 53 69 ; Path=/; SameSi
00a0: 74 65 3d 4c 61 78 0d 0a                         te=Lax..

この受信した Cookie をファイルとして保存したい場合には、-c オプションを指定して curl コマンドを実行します。

-c オプションの引数には Cookie の出力先のファイルのパスを指定します。

例えば下記を実行すれば HTTP レスポンスに設定された Cookie がカレントディレクトリの rcookie.txt に保存されることになります。

% curl -c rcookie.txt [URL]

実際に保存される Cookie は下記のようなものになります。

# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

localhost       FALSE   /       FALSE   1684794910      csrftoken       6uQLfNODeqIFKTIKAfkGd616qj3ae6INest1rZ6nS9W4g0t0pTNDQLheiSWfwbTw

Cookie の送信

保存した Cookie は、-b オプションを指定して curl コマンドを実行することでサーバーに送信することができます(送信する HTTP リクエストに Cookie が設定される)。

-b オプションの引数には送信したい Cookie のファイルのパスを指定します。基本的には -c オプションで保存した Cookie のファイルのパスを指定します。

例えば下記を実行すれば、カレントディレクトリの scookie.txt に保存された Cookie が設定された状態で HTTP リクエストが送信されることになります。

% curl -b scookie.txt {URL}

Coockie を送信している様子に関しても、前述の --trace オプションにより確認することが可能です。

HTTP リクエストのヘッダーの Cookie: csrftoken= 以降の文字列が Cookie となります。

=> Send header, 327 bytes (0x147)
0000: 50 4f 53 54 20 2f 4a 61 6e 6b 65 6e 2f 6a 61 6e POST /Janken/jan
0010: 6b 65 6e 20 48 54 54 50 2f 31 2e 31 0d 0a 48 6f ken HTTP/1.1..Ho
0020: 73 74 3a 20 31 32 37 2e 30 2e 30 2e 31 3a 38 30 st: 127.0.0.1:80
0030: 30 30 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 00..User-Agent: 
0040: 63 75 72 6c 2f 37 2e 36 34 2e 31 0d 0a 41 63 63 curl/7.64.1..Acc
0050: 65 70 74 3a 20 2a 2f 2a 0d 0a 43 6f 6f 6b 69 65 ept: */*..Cookie
0060: 3a 20 63 73 72 66 74 6f 6b 65 6e 3d 56 71 6a 35 : csrftoken=Vqj5
0070: 7a 4c 30 4a 6d 68 68 48 63 69 4c 51 31 71 5a 70 zL0JmhhHciLQ1qZp
0080: 57 41 4c 69 67 68 4d 77 39 59 63 44 50 71 58 69 WALighMw9YcDPqXi
0090: 73 61 4a 4d 33 76 4c 30 46 4b 47 39 37 7a 43 34 saJM3vL0FKG97zC4
00a0: 53 77 51 77 74 46 6c 77 55 70 4e 58 3b 20 73 65 SwQwtFlwUpNX; se
00b0: 73 73 69 6f 6e 69 64 3d 75 70 34 79 64 75 69 32 ssionid=up4ydui2
00c0: 75 6d 7a 38 6b 6b 63 71 71 65 36 6d 7a 6d 74 69 umz8kkcqqe6mzmti
00d0: 33 6b 67 30 79 67 6e 73 0d 0a 43 6f 6e 74 65 6e 3kg0ygns..Conten
00e0: 74 2d 4c 65 6e 67 74 68 3a 20 33 31 36 0d 0a 43 t-Length: 316..C
00f0: 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 6d 75 6c ontent-Type: mul
0100: 74 69 70 61 72 74 2f 66 6f 72 6d 2d 64 61 74 61 tipart/form-data
〜略〜

curl コマンドでログインする

curl コマンドで Cookie を扱う で紹介したオプションを使用して Cookie を扱うことで、curl コマンドからウェブサイトやウェブアプリへのログインを行うようなこともできます。

この際には、まずは単純に下記のように curl コマンドを実行し、ログインページに対して HTTP リクエストを送信します。

% curl [ログインページの URL]

これによりログインページの HTML をサーバーから受信することができます。

さらに、下記のように POST リクエストを送信します。下記はユーザー名を入力するフォームの name 属性が username、パスワードを入力するフォームの name 属性が password である場合の例となります。さらにユーザー名には user、パスワードには pass を指定する形で POST リクエストを送信しています

% curl [ログインページの URL] -c cookie.txt -L -d username=user -d password=pass

このコマンドはあくまでも例であって、実際に -d オプションに指定すべき引数はフォームの name 属性等によって異なるので注意してください。詳細は curl コマンドでフォームの入力&送信を行う をご確認いただければと思います。

上記のコマンドにおける最大のポイントは -c オプションを指定しているところです。

POST リクエストを送信して認証成功した場合、サーバーからユーザー user がログイン中であることを示す Cookie が HTTP レスポンスに設定されて送信されてきます。

その Cookie を -c オプションを指定して保存するようにしています。

また、ログイン後にはリダイレクトされるケースが多いので、-L オプションを指定してリダイレクト先に自動的に転送されるようにしています。

上記コマンドを実行することで、ログインに成功した場合はログイン成功後のページの HTML を受信することになります。

さらに、次はログイン中でないと表示できないページに対して HTTP リクエストを送信してみましょう。

% curl [ログイン中でないと表示できないページの URL] -b cookie.txt -L

ポイントは -b オプションを指定しているところです。

-b オプションの引数には先ほど curl コマンド実行時に保存した Cookie のファイルのパスを指定しています。ユーザー user としてログイン成功した際にサーバーから送られてきた Cookie であり、この Cookie は user がログイン中であることを示す値となります。

これを送信することで、サーバーはリクエスト送信元のユーザーが user であり、さらにログイン中であることを識別することができます。そのため、サーバーはログイン中でないと表示できないようなページへのリクエストであっても、レスポンスとしてそのページの HTML を送信してくることになります。

もし、下記のように Cookie を送信しなかったのであれば、もちろんサーバー側でのログイン管理の仕方にも依るかも知れませんが、基本的にはサーバーはリクエスト送信元のユーザーがログイン中であると判別することができないため、エラー等が表示される HTML を送信したりログイン画面のページへリダイレクトすることが多いと思います。

% curl [ログイン中でないと表示できないページの URL] -L

こんな感じで、POST や Cookie を利用することでウェブサイトやウェブアプリへのログインが可能ですし、ログイン中の状態を保持したまま他のページへの HTTP リクエストを送信するようなことも可能になります。

スポンサーリンク

curl コマンドでフォームに設定されたトークンを送信する

また、多くのウェブサイトやウェブアプリにおいては、サイトやアプリに対する攻撃を防ぐための様々な対策が行われています。その1つが CSRF 対策になります(CSRF 対策については必要に応じて別途ググって調べてみてください)。

この対策が施されているサイトにおいては、フォームの内容を送信する際に「トークン」と呼ばれる値を含めて送信しないとエラーになる場合があります。

curl コマンドでフォームの入力&送信を行う で、入力フォームの HTML の例として下記を紹介しました。

入力フォームのHTML
<form action="/app/" method="post">
    <p>
        <label for="id_namae">名前:</label>
        <input type="text" name="namae" value="test" maxlength="100" required id="id_namae">
    </p>
    <p>
        <label for="id_nenrei">年齢:</label>
        <input type="number" name="nenrei" value="5" required id="id_nenrei">
    </p>
    <p><input type="submit" value="送信"></p>
</form>

全く見た目が同じ入力フォームであっても、下記の1つ目の input タグのように、追加で input タグが用意されている場合があります。type="hidden" は表示しないという意味合いの属性であり、実際には1つ目のタグに対応する入力フォームは表示されません。

ちなみに、下記の HTML は Django で開発したウェブアプリの入力フォームの HTML の実例となります。

CSRF対策された入力フォームのHTML
<form action="/app/" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="2EbuGp0G8ilq1v5HokTgRKfkl3h4DYKUWEPHzOJJPwPJuX00utwVNGkyyrQ4ople">
    <p>
        <label for="id_namae">名前:</label>
        <input type="text" name="namae" value="test" maxlength="100" required id="id_namae">
    </p>
    <p>
        <label for="id_nenrei">年齢:</label>
        <input type="number" name="nenrei" value="5" required id="id_nenrei">
    </p>
    <p><input type="submit" value="送信"></p>
</form>

上記の HTML において、value 以降の文字列が前述のトークンとなります。

このトークンは HTML を受信するたび(ページを表示するたび)に変化するワンタイムパスワードとなり、このトークンが入力フォームを含む HTML を受信したことを示す証拠となります(ページを表示しないとトークンは得られないので、このトークンを知っているということは、その HTML を受信した本人であることを示す証拠となる)。

こういった入力フォームの場合、単にフォームに入力した値だけでなく、トークンも一緒にサーバーに送信しないとエラーになることがあります。

ただ、送信の仕方は単純で、単に POST リクエストでトークンも含めて送信を行えば良いだけです。

より具体的には、上記の HTML ではトークンが name="csrfmiddlewaretoken" の要素の value に設定されているため、次のように curlコマンドでトークンを送信してやれば良いことになります。

% curl [URL] -d namae=daeu -d nenrei=18 -d csrfmiddlewaretoken=2EbuGp0G8ilq1v5HokTgRKfkl3h4DYKUWEPHzOJJPwPJuX00utwVNGkyyrQ4ople

この辺りのトークンの送信もウェブブラウザを利用する場合は勝手に行なってくれますが、curl コマンドの場合は明示的にトークンを送信するようオプションを指定する必要があります。

前述の通り、上記の HTML は Django で開発したウェブアプリの入力フォームのものであり、ウェブアプリやウェブサイトの作り方や利用されるフレームワークによって、トークンの送信の仕方等が異なるので注意してください。

とりあえず Django の場合は、入力フォームを送信する際に基本的には上記のようにトークンを送信する必要があるようです。

もっと言えば、Django の場合はログイン後のページを表示するような場合だけでなく、単に入力フォームを送信する時にも Cookie の送信が求められます。つまり、入力フォームを送信する場合は Cookie と上記のトークンの2つの送信が求められます。

なので、実は上記のコマンドでは Cookie が送信されていないのでエラーになります。

そのため、本当であれば、まずは下記のように curl コマンドを実行して Cookie の保存と入力フォームの HTML の受信を行い、

% curl [URL] -c cookie.txt

さらに、その HTML からトークンをコピーし、下記のように Cookie とトークンの両方を送信してやる必要があります。

% curl [URL] -b cookie.txt -d namae=daeu -d nenrei=18 -d csrfmiddlewaretoken=コピーしたトークン

このように、セキュリティ対策がしっかり施されているようなサイトやアプリの場合は curl コマンドのオプション指定が複雑になることが多く、POST リクエストを送信してもエラーになってしまうケースも多いと思います。

この場合、エラーを表示するための HTML が受信されるはずので、その HTML をウェブブラウザで開いて何のエラーが発生しているかをまずは確認してみると良いと思います。

curl コマンドで Basic 認証を行う

curl コマンドでログインするcurl コマンドでログインを行う例を紹介しました。

ログイン時にはユーザー名やパスワードが正しいかどうかの認証が行われるのですが、認証の仕方に様々なものがあり、curl コマンドでログインする で紹介したのは下の画像のようにページに用意されたログインフォームからユーザー名やパスワードを送信して認証を行う際の curl コマンドの実行例となります。

ログインフォームからのログイン画面を示す図

この場合は、curl コマンドで入力フォームの内容を POST リクエストで送信しましたね!

他にも有名な認証方法として Basic 認証と呼ばれる認証があります。ウェブブラウザを使用してページを表示しようとした際に、ページが表示されることなく、ウェブブラウザから下の図のようにユーザー名とパスワードの入力が求められることがあると思いますが、このような場合、Basic 認証が行われている可能性があります。

Basic認証が行われる様子

こういった認証が行われる際には、上記のように入力フォームの内容を POST リクエストで送信するのではなく、curl コマンドに -u オプションを指定してユーザー名とパスワードを送信することになります。

-u オプションの引数には、下記のようにユーザー名とパスワードを : で区切って指定します。

% curl [URL] -L -u ユーザー名:パスワード

例えばユーザー名が user でパスワードが pass の場合は下記のように curl コマンドを実行します。

% curl [URL] -L -u user:pass

これにより、ユーザー名とパスワードがサーバーに送信され、認証 OK であれば、リクエストした URL のページの HTML を受信することができます。

また、下記のように -u オプションの引数にユーザー名のみを指定した場合、コマンド実行後にパスワードの入力が促されることになります。パスワードを入力してエンターキーを押下すれば、サーバーにユーザー名やパスワードが送信されて認証が行われます。

% curl [URL] -L -u user
Enter host password for user 'user':

まとめ

このページでは、curl コマンドの紹介を行いました!

curl コマンドを利用することで、ウェブブラウザで行われているサーバーとのデータの送受信をコマンドから行うことができるようになります。

これにより、ウェブブラウザ上でマウス等を使った操作をコマンドから実現でき、操作の自動化等を行うことも可能になります。

また、POST リクエストや Cookie の送信などは普段はウェブブラウザが勝手に行なってくれていて存在自体を知らなかった人もおられるのではないかと思います。

curl の場合はこれらを意識しながらコマンドを実行する必要があるため、自然とこういったウェブや HTTP の知識も身につくと思います。

特にウェブアプリ開発などを行う方であれば身につけておいて損はない知識ばかりだと思いますので、そういった知識を身につけるためにも curl コマンドを利用してみても良いと思います!

同じカテゴリのページ一覧を表示

コメントを残す

メールアドレスが公開されることはありません。