台風直撃の朝。
tl;dl
- 先日立ち上げた Redmine 環境に対して JMeter で負荷テストを行う為のシナリオを作ってみようと思った
- 但し HTTP リクエストをポチポチ作るのは辛いと思ったら HTTP プロキシサーバ(HTTP(S) Test Script Recorder)という機能を利用すると少し捗りそうな気がした
ということで、雑なメモ。
参考
- https://blazemeter.com/blog/how-load-test-csrf-protected-web-sites
- http://jmeter.apache.org/usermanual/component_reference.html#HTTP%28S%29_Test_Script_Recorder
- http://qiita.com/t_cyrill/items/9d5376f38b4c15fd4eb1
ありがとうございます。
メモ
JMeter における HTTP プロキシサーバとは
JMeter を日本語環境で起動した場合には「HTTP プロキシサーバ」と表示されるが、JMeter 2.10 以降は HTTP(S) Test Script Recorder という名前の機能のようだ。
いつものざっくり意訳で...
という機能。
準備
ブラウザ側の設定
今回は Google Chrome を利用するので Google Chrome にて Proxy サーバーの設定を行う。
尚、利用した Chrome のバージョンは バージョン 44.0.2403.157 m
という最新のバージョン。
JMeter 側の設定
JMeter を起動して以下の設定を行う。
- スレッドグループを作成
- [ワークベンチ]→[追加]→[Non-Testエレメント]→[HTTP プロキシサーバ]を選択
- [対象となるコントローラ]にて 2. で作成したスレッドグループを指定
- 任意だが [Add suggested Excludes] をクリックして記録を除外するコンテンツの拡張子を指定する(ことも出来る)
- [開始] をクリックして記録を開始する
利用した JMeter のバージョンは 2.13 で Java のバージョンは...
Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. C:\Users\kappa>java -version java version "1.8.0_51" Java(TM) SE Runtime Environment (build 1.8.0_51-b16) Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode) C:\Users\kappa>
となる。
記録開始
HTTP プロキシサーバの [開始] をクリックしてブラウザアクセスの記録を開始する。
適当にブラウザアクセスを行う。
リクエストの内容を見てみる
ひとしきりブラウザアクセスをしたら [停止] をクリックして「HTTP リクエスト」の内容を見てみる。
ちゃんと HTTPS アクセスで POST メソッドの内容も記録されている。
実際にシナリオを利用して負荷をかけてみる(1)
記録したシナリオを利用して負荷を掛けてみると以下のようにログイン、ログアウトの処理が失敗している。
理由は...
- Rails アプリケーションは CSRF(クロスサイトリクエストフォージェリ )対策がデフォルトで行われておりリクエストパラメータに
authenticity_token
というパラメータを付与する - 今回 HTTP プロキシサーバで記録された
authenticity_token
の値が不正な値として検証に失敗しログイン、ログアウトの処理でエラーが発生してしまっている為
Redmine の production.log にも以下のように記録されている。
Started GET "/login" for xxx.xxx.xxx.xxx at 2015-08-24 20:19:32 +0000 Processing by AccountController#login as HTML Current user: anonymous Rendered account/login.html.erb within layouts/base (2.2ms) Completed 200 OK in 20ms (Views: 14.3ms | ActiveRecord: 0.9ms) Started POST "/login" for xxx.xxx.xxx.xxx at 2015-08-24 20:19:32 +0000 Processing by AccountController#login as HTML Parameters: {"utf8"=>"?", "authenticity_token"=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==", "back_url"=>"http://xxx.xxx.xxx.xxx/", "username"=>"user", "password"=>"[FILTERED]", "login"=>"ログイン ≫"} Can't verify CSRF token authenticity
CSRF 対策の処理を HTTP リクエストに加える
ということで...
CSRF 対策の処理は各アプリケーションによって若干は異なるかもしれないが、Redmine の場合には /login
の場合には最初に GET /login
の際にレスポンスボディの meta-data
含まれる csrf-token
から取得する。
- 参照名には
LOGIN_CSRF_TOKEN
を定義して後の [HTTP リクエスト] で参照出来るようにする - 正規表現には を指定して
meta-data
からcsrf-token
を取得する - テンプレートには
$1$
を指定する
[HTTP リクエスト] に [後処理] → [追加] → [正規表現抽出] で追加して、上記のパラメータを定義しておく。
次に実際のログイン処理を行う POST /login
処理のパラメータとして csrf-token
を利用するように設定する。
authenticity_token
に上記で定義しておいた参照名(LOGIN_CSRF_TOKEN
)を変数として定義する- その他のパラメータについては記録された状態の値を踏襲する
[HTTP プロキシサーバ]で記録しておいたパラメータに対して上記の通りの修正を加える。尚、ログアウトの処理(/logout
)に関しても同様の処理を行う。
尚、以下にサンプルのシナリオをアップしておく。
実際にシナリオを利用して負荷をかけてみる(2)
最後に cookie も利用しているようなので [oreno-thread] → [追加] → [HTTP クッキーマネージャ] でスレッドグループに追加してから改めて記録したシナリオで負荷を掛けてみる。
とりあえず全てのアクセスが成功していることを確認。
[統計レポート] でもリクエストエラー等は検出されていないことを確認。
まとめ
HTTP プロキシサーバを利用することで
- [HTTP リクエスト] を書く手間が省ける
- ログイン、ログアウト処理等がある場合には適宜一手間加える必要がある
Rails アプリケーションでログイン、ログアウトの処理をシナリオにする場合には
- CSRF 対策が入っている(Rails 4 以上はデフォルトで設定されているとのこと)
- [正規表現抽出] を利用してログイン処理前等のレスポンスヘッダ、レスポンスボディから CSRF トークンを取得してログイン処理に含めるようにする
- [HTTP クッキーマネージャ] も追加しておくと良さそう
その他
- [結果をツリーで表示] を設定しておくと [HTTP リクエスト] のデバッグに役立つ
ということで、やっと負荷試験を出来る準備が整った。
以上。