$30 off During Our Annual Pro Sale. View Details »

チャットディーラーの高速開発を支えるLaravel / phpkansai 2018 Cha...

チャットディーラーの高速開発を支えるLaravel / phpkansai 2018 ChatDealer Rapid Development with Laravel

坂田晃平

July 14, 2018
Tweet

More Decks by 坂田晃平

Other Decks in Technology

Transcript

  1. 自己紹介 • 名前:坂田 晃平 • 所属:株式会社ラクス – メールディーラーと チャットディーラーの開発を担当 •

    経歴: – 2016 年 新卒入社(3 年目) – PHP の使用歴も 3 年目 • メールディーラー :ノンフレームワーク • チャットディーラー:Laravel 1
  2. • はじめに • チャットディーラー(ChatDealer)とは • なぜ Laravel を選択したか? • Laravel

    で良かったこと • Laravel で困ったこと • まとめ 今日話すこと 2
  3. 10 年以上 PHP でノンフレームワークで開発・運用されてきた主力サービ ス(メールディーラー)の開発チームが、新規に姉妹サービス(チャット ディーラー)を立ち上げる際に Laravel を選択をしました。 開発期間半年というスピードが求められる中で、チームが Laravel

    に抱い た理想と現実、また、Laravel (Blade) と Vue.js の組み合わせにより発生 した脆弱性への対応など、Laravel での新規サービス立ち上げの経験を具 体的にお伝えします。 <セッション概要>より 4
  4. • 2001 年にサービス提供開始 • 4,000 社以上の導入実績 • メール共有・管理システム市場で 9 年連続

    シェア No.1 • PHP でノンフレームワークで開発 7 メールディーラー(MailDealer)とは
  5. • PHP 4 時代にサービスの土台を開発 (参考) PHP 4.0 リリースが 2000/05/22 •

    長期間改修されてきたソースコード – ソースコードの構成が機能ごとにちぐはぐ – ビューとロジックが分離されていない – リクエストパラメータの受け渡しが煩雑 – バリデーションが煩雑 – etc… • メンテナンス性の低下 8 課題
  6. • PHP 4 時代にサービスの土台を開発 (参考) PHP 4.0 リリースが 2000/05/22 •

    長期間改修されてきたソースコード – ソースコードの構成が機能ごとにちぐはぐ – ビューとロジックが分離されていない – リクエストパラメータの受け渡しが煩雑 – バリデーションが煩雑 – etc… • メンテナンス性の低下 9 課題 課題感をもつ開発チームが新サービスを立ち上げ!
  7. 技術スタック • 言語、フレームワーク – PHP 7.1、Laravel 5.5 – Node.js、Express、Socket.IO •

    開発環境 – PhpStorm、Jenkins、Redmine、GitLab、 Mattermost • インフラ – 仮想基盤(オンプレ)、nginx、Apache、 PostgreSQL 9.6、Redis 13
  8. 開発スケジュール 15 2月 3月 4月 5月 6月 7月 要件定義 2017年

    開発基盤整備 設計 実装・単体テスト システム テスト β版フィード バック改修 β版リリース 本番リリース
  9. はじめに • 新サービスの立ち上げに際しての課題 – 短納期(6 ヶ月) • 実装の期間は実質 2 ヶ月

    • 開発効率の向上必須 – レガシーからの脱却 • レガシーシステムの課題を解決 • 開発チームはフレームワークを使っていない 17
  10. 18 レガシーシステムでの課題(再掲) • PHP 4 時代にサービスの土台を開発 • 長期間改修されてきたソースコード – ソースコードの構成が機能ごとにちぐはぐ

    – ビューとロジックが分離されていない – リクエストパラメータの受け渡しが煩雑 – バリデーションが煩雑 – etc… • メンテナンス性の低下
  11. • 実装工数の短縮 • メンテナンス性の向上 – MVC モデルによるコードの分離 – コーディングルールやファイル構成の標準化 –

    リクエスト情報の管理方法の標準化 – 一般的な脆弱性への対策 19 フレームワークに期待すること
  12. 選定条件:長期サポート • シェア率が高い人気のフレームワークを調査 – 調査段階では、日本では CakePHP に続き Laravel がシェア 2

    位だった – 世界では Laravel が圧倒的に使用されている – Laravel のシェア率の伸びが一番大きい – コミュニティが活発 22
  13. 選定条件:長期サポート • Laravel は LTS に対応 – Laravel 5.1 より

    LTS に対応した – バグフィックスは 2 年間、セキュリティーパッ チの提供は 3 年間 – 新サービス開発開始の半年後に新たな LTS バー ジョン (5.5) がリリース予定 24
  14. 選定条件:機能性 • 基本機能 – ルーティング – テンプレートエンジン (Blade) – 扱いやすいバリデーター

    – 認証、セッション管理、エラーハンドリング等 の基本機能 – 一般的な脆弱性への対策 25
  15. 選定条件:機能性 • 便利機能やライブラリを調査 – マイグレーション – ページネーション – 様々なミドルウェアやサービスと連携できる •

    Redis でのキャッシュ管理など – 主要なライブラリが含まれる • Bootstrap, jQuery, Vue.js など – ユニットテストの作成が容易 • PHPUnit をサポート 26
  16. フレームワーク選定のまとめ 下記の点から、 新サービスのフレームワークに Laravel を採用する事となった • 長期サポート – LTS バージョンがある

    – 一番人気で、今なお人気上昇中 – コミュニティも活発 • 機能性 – フルスタックフレームワークであること 27
  17. オールインワンでスピード開発に向いていた • 準備コストが削減できたので、ロケットス タートを決めることができた – フレームワークの標準機能 ルーティング、Middleware、DI、バリデーション、 テンプレートエンジン (Blade)、バッチ処理 (Command)、

    マイグレーション、デバッグ、クエリビルダ、ページネーション、 セッション – ライブラリ、ミドルウェア・サービスとの統合 Composer、Bootstrap、jQuery、Vue.js、PostgreSQL、 Redis、PHPUnit 31
  18. 標準ライブラリが使いやすい • テンプレートエンジン(Blade) – 覚えることが少なく、なじみやすいシンタック ス – Blade ファイルは PHP

    ファイルにコンパイルさ れ、変更が無い限りはコンパイルした PHP ファ イルを呼び出すので軽量(らしい) – 他のテンプレートエンジンとくらべ制約が緩く、 @php ディレクティブで PHP コードの記述もで きる 40
  19. • バッチ処理(Command) – Laravel の場合 • cron は 1 レコードのみ

    • 実行スケジュールを PHP で記述できる 標準ライブラリが使いやすい 45
  20. • マイグレーション – ノンフレームワークサービスの場合 – Laravel の場合 アプリケーションのバージョンより、 新しいバージョンをファイル名に含 むパッチファイルを実行

    コマンドを実行するだけで、マイグ レーションファイルの中から未実行 のファイルのみを自動実行 ロールバックも可能 47 標準ライブラリが使いやすい
  21. Blade (SSR) + Vue.js での脆弱性 • Laravel 標準の認証画面に XSS の問題

    – ある時のリリースノート > In Laravel 5.6.9 and Laravel 5.5.37, a potential XSS > vector was patched in the default Bootstrap > scaffolding that ships with laravel. > Laravel 5.6.9 と 5.5.37 では、標準のスキャフォール > ディングで、潜在的な XSS の可能性が修正されました。 https://laravel-news.com/laravel-5-6-9 56
  22. • Laravel 標準の認証画面に XSS の問題 – ある時のリリースノート > In Laravel

    5.6.9 and Laravel 5.5.37, a potential XSS > vector was patched in the default Bootstrap > scaffolding that ships with laravel. Laravel 5.6.9 と 5.5.37 では、標準のスキャフォールディ ングで、潜在的な XSS の可能性が修正されました Blade (SSR) + Vue.js での脆弱性 https://laravel-news.com/laravel-5-6-9 57 XSS なんて怖いわぁ…。 標準のスキャフォールディングは使っ てないし関係ないっぽいけど。 でも、どこで XSS になってるんやろ?
  23. • Laravel 標準の認証画面に XSS の問題 – ある時のリリースノート > In Laravel

    5.6.9 and Laravel 5.5.37, a potential XSS > vector was patched in the default Bootstrap > scaffolding that ships with laravel. Laravel 5.6.9 と 5.5.37 では、標準のスキャフォールディ ングで、潜在的な XSS の可能性が修正されました Blade (SSR) + Vue.js での脆弱性 https://laravel-news.com/laravel-5-6-9 58 XSS なんて怖いわぁ…。 標準のスキャフォールディングは使っ てないし関係ないっぽいけど。 でも、どこで XSS になってるんやろ? 実は、、、関係あった! (調べてよかった…)
  24. Blade (SSR) + Vue.js での脆弱性 • サーバーサイドレンダリング (SSR) と Vue.js

    との組み合わせで起こりうる XSS – Blade との組み合わせに限らない – 実は Vue.js 特有というわけでもない • AngulerJS ではもっと前(2014 年くらい)から話題 になっていたらしい https://havelog.ayumusato.com/develop/security/e593- mixins_server_template_and_angular.html 59
  25. • SSR と Vue.js の組み合わせで起こる XSS サーバーでの処理 ブラウザでの処理 Blade (SSR)

    + Vue.js での脆弱性 <div id="app"> {{ $name }} </div> sample.blade.php Blade で処理 $name = “{{ alert(‘XSS') }}” <div id="app"> {{ alert(&apos;XSS&apos;) }} </div> <div id="app"> {{ alert(‘XSS’) }} </div> Vue.js が処理 <div id="app"> </div> 60 {{ … }} の中の スクリプトが実行 される! 処理済みのHTMLデータ レスポンス送信 ブラウザが読込
  26. • SSR と Vue.js の組み合わせで起こる XSS サーバーでの処理 ブラウザでの処理 Blade (SSR)

    + Vue.js での脆弱性 <div id="app"> {{ $name }} </div> sample.blade.php Blade で処理 $name = “{{ alert(‘XSS') }}” <div id="app"> {{ alert(&apos;XSS&apos;) }} </div> <div id="app"> {{ alert(‘XSS’) }} </div> Vue.js が処理 <div id="app"> </div> 61 {{ … }} の中の スクリプトが実行 される! 処理済みのHTMLデータ レスポンス送信 ブラウザが読込
  27. • SSR と Vue.js の組み合わせで起こる XSS – Vue.js で処理される領域にユーザー入力の文字 列を

    SSR で埋め込むと危険 – “mustache injection” と(個人的に)呼んで る {{…}} ← これを Mustache 構文と呼ぶことから – 知らなかったら普通に作ってしまいそう Blade (SSR) + Vue.js での脆弱性 62
  28. • SSR と Vue.js の組み合わせで起こる XSS – Vue.js で処理される領域にユーザー入力の文字 列を

    SSR で埋め込むと危険 – “mustache injection” と(個人的に)呼んで る {{…}} ← これを Mustache 構文と呼ぶことから – 知らなかったら普通に作ってしまいそう • 知らなかったし、実際作ってしまっていた Blade (SSR) + Vue.js での脆弱性 63
  29. Blade (SSR) + Vue.js での脆弱性 • mustache injection 対策案1 (不採用)

    – “{” や “}” を HTML エスケープ • 効果なし サーバー側でエスケープしても、Vue.js が処理する 時にはブラウザによってもとに戻されてしまっている 64 サーバーでの処理 <div id="app"> &#123;&#123; alert(&apos;XSS&apos;) &#125;&#125; </div> <div id="app"> {{ escapeMustache($name) }} </div> sample2.blade.php ブラウザでの処理 <div id="app"> {{ alert(‘XSS’) }} </div> $name = “{{ alert(‘XSS') }}”
  30. Blade (SSR) + Vue.js での脆弱性 • mustache injection 対策案2 (不採用)

    – “v-pre” ディレクティブの利用 • Laravel のスキャフォールディングでの対策 • 効果は実証されている • 結果:対象箇所が多すぎる・新しく書く時も必ずつけ る必要・忘れそう 65 ブラウザでの処理 <div id="app"> <span v-pre>{{ alert(‘XSS’) }}</span> </div> v-pre の要素内は Vue.js で処理されない
  31. Blade (SSR) + Vue.js での脆弱性 • mustache injection 対策案3 (不採用)

    – “{{” や “}}” の文字間に半角空白を挿入する • “{” や “}” のHTMLエンティティ表現に対しても同様 に処理が必要 ↓ • “{”、“&#123;”、“&#x7b;” のうち 2 つの組み合わせ • “}”、“&#125;”、“&#x7d;” のうち 2 つの組み合わせ • さらにそれらが連続している場合でも漏れなく空白を 入れる必要がある 66 サーバーでの処理 {&#123;{&#x7b{ … }&#x7d}&#125;} 危険な文字列: { &#123; { &#x7b; { … } &#x7d; } &#125; } 無害な文字列:
  32. Blade (SSR) + Vue.js での脆弱性 • mustache injection 対策案 (3)

    – “{{” や “}}” の文字間に半角空白を挿入する • “{” や “}” のエンティティ表現に対しても同様に処理 が必要 ↓ • “{”、“&#123;”、“&#x7b;” のうち 2 つの組み合わせ • “}”、“&#125;”、“&#x7d;” のうち 2 つの組み合わせ • さらにそれらが連続している場合でも漏れなく空白を 入れる必要がある 67 サーバーでの処理 {&#123;{&#x7b{ … }&#x7d}&#125;} 危険な文字列: { &#123; { &#x7b; { … } &#x7d; } &#125; } 無害な文字列: $replacementMap = [ "{{" => "{ {" , "{&#123;" => "{ &#123;" , "{&#x7b;" => "{ &#x7b;" , "&#123;&#123;" => "&#123; &#123;" , "&#123;{" => "&#123; {" , "&#123;&#x7b;" => "&#123; &#x7b;" , "&#x7b;&#x7b;" => "&#x7b; &#x7b;" , "&#x7b;{" => "&#x7b; {" , "&#x7b;&#123;" => "&#x7b; &#123;" , "}}" => "} }" , "}&#125;" => "} &#125;" , "}&#x7d;" => "} &#x7d;" , "&#125;&#125;" => "&#125; &#125;" , "&#125;}" => "&#125; }" , "&#125;&#x7d;" => "&#125; &#x7d;" , "&#x7d;&#x7d;" => "&#x7d; &#x7d;" , "&#x7d;}" => "&#x7d; }" , "&#x7d;&#125;" => "&#x7d; &#125;" ];
  33. Blade (SSR) + Vue.js での脆弱性 • mustache injection 対策案4 (採用)

    – “{{” や “}}” の文字間に半角空白を挿入する – いつやるか? • 出力時 ⇒ “v-pre” 使用と同様の問題。対象箇所が多い・忘れ そう • 入力時 ⇒ Middleware ですべてのリクエストパラメータを処 理すれば確実 – 根本的な解決は…(^ω^; • SPA 化しかない? 68
  34. Vue.js は思ったより難しかった 70 • 開発を始める前は… – チームメンバーはみな jQuery に慣れ親しんで いる(特にベテラン)

    – Vue.js は「学習コストが低い」という前評判 – 軽く公式のガイドを見てもそんな印象 • 内容を表示させたい場所に `v-bind:` ってつければ 表示される! • しかもモデルの値を変えたら自動で反映される! – 確かに簡単そうだ(と思ってしまった) • そのまま開発に突入
  35. Vue.js は思ったより難しかった 71 • 開発を始めてみると… – Vue インスタンスが紐づいた要素内の子要素を 別の Vue

    インスタンスで制御したい – 離れた場所にある別々の要素を同じ Vue インス タンスで制御したい – jQuery や Bootstrap のライブラリと一緒に使 いたい – モデルの値を変えてるはずなのに反映されない
  36. Vue.js は思ったより難しかった 72 • 開発を始めてみると… – Vue インスタンスが紐づいた要素内の子要素を 別の Vue

    インスタンスで制御したい – 離れた場所にある別々の要素を同じVueインスタ ンスで制御したい – jQuery や Bootstrap のライブラリと一緒に使 いたい – モデルの値を変えてるはずなのに反映されない いったいどうすればいいの…?
  37. Vue.js は思ったより難しかった 73 • 開発を始めてみると… – Vue インスタンスが紐づいた要素内の子要素を 別の Vue

    インスタンスで制御したい ⇒ 内部の要素はコンポーネントを作ってそれで置き換 えましょう – 内部の要素に `v-pre` を付けてもできるけど… – 離れた場所にある別々の要素を同じ Vue インス タンスで制御したい ⇒ コンポーネントにすれば再利用できます
  38. Vue.js は思ったより難しかった 74 • 開発を始めてみると… – jQuery や Bootstrap のライブラリと一緒に使

    いたい ⇒ ラッパーコンポーネントを作れば比較的楽に統合で きます – モデルの値を変えてるはずなのに反映されない ⇒ 配列やオブジェクトの要素を変更する場合は特別な やり方があるので注意!
  39. Vue.js は思ったより難しかった 75 • jQuery 脳からのパラダイムシフトが必要? – 「jQuery でなら作り方わかってるのに」 –

    利き手でない方の手で字を書くかのよう… – 結局慣れるしかない • jQuery 系ライブラリとの相性 – 仮想 DOM から DOM への変更が実際に反映さ れるのを待つ必要あり – ノウハウの蓄積
  40. Vue.js は思ったより難しかった 76 • 「学習コストが低い」とは言え、やっぱり ちゃんと勉強しないとだめだった – 最近は日本語で読める入門記事もどんどん増え ていて学習しやすくなっている印象 •

    少し複雑なことをしたいときはコンポーネン ト化が必須 – コンポーネントの考え方が分かりにくいとの声 もあるが – そこは勉強してもらうしかない
  41. まとめ • フレームワークがスピード開発に役立った – ミドルウェアとの連携設定 – MVC の考えに沿ったソース配置 – ビジネスロジックへの集中ができた!

    • とくに Laravel で良かったこと – 豊富な機能 – 日本語公式ドキュメント – 活発なコミュニティ • 脆弱性への対応も早かった 78
  42. まとめ • Vue.js との組み合わせには注意 – 脆弱性への対応を後からするのは大変 • Vue.js もちゃんと勉強しよう •

    Laravel の豊富な機能を使いこなせない – アイデアをぜひ教えてほしいです! 79