Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

97a42cc1630ebdfdaaa8d50078a9fd3d?s=128

坂田晃平

July 14, 2018
Tweet

Transcript

  1. の高速開発を支える Laravel 株式会社ラクス 坂田晃平 PHP カンファレンス関西 2018

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

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

    で良かったこと • Laravel で困ったこと • まとめ 今日話すこと 2
  4. はじめに 3

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

    に抱い た理想と現実、また、Laravel (Blade) と Vue.js の組み合わせにより発生 した脆弱性への対応など、Laravel での新規サービス立ち上げの経験を具 体的にお伝えします。 <セッション概要>より 4
  6. 5 https://www.maildealer.jp/products/ メールディーラー(MailDealer)とは • 問合せメールを一元的に管理・共有する メール対応サポートツール(SaaS)

  7. • 2001 年にサービス提供開始 • 4,000 社以上の導入実績 • メール共有・管理システム市場で 9 年連続

    シェア No.1 6 メールディーラー(MailDealer)とは
  8. • 2001 年にサービス提供開始 • 4,000 社以上の導入実績 • メール共有・管理システム市場で 9 年連続

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

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

    長期間改修されてきたソースコード – ソースコードの構成が機能ごとにちぐはぐ – ビューとロジックが分離されていない – リクエストパラメータの受け渡しが煩雑 – バリデーションが煩雑 – etc… • メンテナンス性の低下 9 課題 課題感をもつ開発チームが新サービスを立ち上げ!
  11. チャットディーラー(ChatDealer)とは 10

  12. サービス概要 • Web ページに専用スクリプトを埋め込んで 利用する Web チャットシステム(SaaS) • 本文 11

    https://www.chatdealer.jp/products/
  13. サービス概要 • Web ページに専用スクリプトを埋め込んで 利用する Web チャットシステム(SaaS) • 本文 12

    https://www.chatdealer.jp/products/
  14. 技術スタック • 言語、フレームワーク – PHP 7.1、Laravel 5.5 – Node.js、Express、Socket.IO •

    開発環境 – PhpStorm、Jenkins、Redmine、GitLab、 Mattermost • インフラ – 仮想基盤(オンプレ)、nginx、Apache、 PostgreSQL 9.6、Redis 13
  15. 開発チーム構成 • プロジェクトマネージャー • エンジニア – toB 向けバックエンド (PHP):3名 –

    toC 向けフロントエンド (Node.js):3名 14
  16. 開発スケジュール 15 2月 3月 4月 5月 6月 7月 要件定義 2017年

    開発基盤整備 設計 実装・単体テスト システム テスト β版フィード バック改修 β版リリース 本番リリース
  17. なぜ Laravel を選択したか? 16

  18. はじめに • 新サービスの立ち上げに際しての課題 – 短納期(6 ヶ月) • 実装の期間は実質 2 ヶ月

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

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

    リクエスト情報の管理方法の標準化 – 一般的な脆弱性への対策 19 フレームワークに期待すること
  21. フレームワーク選定 • フレームワークに期待する要件は次の2点 – 長期サポート – 機能性 20

  22. 選定条件:長期サポート • すぐにサポート切れしてはメンテナンス性が 悪くなる • 長期サポートされる条件を検討 – 使用者数が多く、人気がある – 活発なコミュニティ

    – LTS (Long-Term Support) を宣言している 21
  23. 選定条件:長期サポート • シェア率が高い人気のフレームワークを調査 – 調査段階では、日本では CakePHP に続き Laravel がシェア 2

    位だった – 世界では Laravel が圧倒的に使用されている – Laravel のシェア率の伸びが一番大きい – コミュニティが活発 22
  24. 選定条件:長期サポート https://trends.google.co.jp/trends/explore?date=today%205- y&q=Laravel,CakePHP,Symfony,CodeIgniter,FuelPHP 23 • Google トレンドでの比較 Laravel は一番人気 があり、上昇し続け

    ている
  25. 選定条件:長期サポート • Laravel は LTS に対応 – Laravel 5.1 より

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

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

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

    – 一番人気で、今なお人気上昇中 – コミュニティも活発 • 機能性 – フルスタックフレームワークであること 27
  29. Laravel で良かったこと 28

  30. Laravel で良かったこと • オールインワンでスピード開発に向いていた • 簡単設定でどんなものにも繋がる • 標準ライブラリが使いやすい • ドキュメントが充実していた

    29
  31. Laravel で良かったこと • オールインワンでスピード開発に向いていた • 簡単設定でどんなものにも繋がる • 標準ライブラリが使いやすい • ドキュメントが充実していた

    30
  32. オールインワンでスピード開発に向いていた • 準備コストが削減できたので、ロケットス タートを決めることができた – フレームワークの標準機能 ルーティング、Middleware、DI、バリデーション、 テンプレートエンジン (Blade)、バッチ処理 (Command)、

    マイグレーション、デバッグ、クエリビルダ、ページネーション、 セッション – ライブラリ、ミドルウェア・サービスとの統合 Composer、Bootstrap、jQuery、Vue.js、PostgreSQL、 Redis、PHPUnit 31
  33. Laravel で良かったこと • オールインワンでスピード開発に向いていた • 簡単設定でどんなものにも繋がる • 標準ライブラリが使いやすい • ドキュメントが充実していた

    32
  34. 簡単設定でどんなものにも繋がる • チャットディーラーで利用しているミドル ウェアの一例 – PostgreSQL – Redis – Postfix

    いずれも、接続のための仕組みは準備されており、 簡単設定で繋がった 33
  35. Laravel で良かったこと • オールインワンでスピード開発に向いていた • 簡単設定でどんなものにも繋がる • 標準ライブラリが使いやすい • ドキュメントが充実していた

    34
  36. 標準ライブラリが使いやすい • ルーティング – URL とコントローラの紐づけが直観的に書けて わかりやすかった 35

  37. 標準ライブラリが使いやすい • Middleware – HTTP リクエストをフィルタリングする機能 – リクエスト処理の事前チェックや事後処理を Middleware に実装、適用したいルーティング設

    定を group メソッドで囲うだけ – 認証処理などを Middleware に実装にしたこと で、ビジネスロジックに専念できた 36
  38. 標準ライブラリが使いやすい • DI – メソッドインジェクション機能が便利 – タイプヒントするだけで、メソッドの引数にオ ブジェクト注入される 37

  39. 標準ライブラリが使いやすい • バリデーション – Request クラスにバリデーションルールを追加 し、コントローラーメソッドでタイプヒントす るだけ – コントローラーメソッドに、バリデーション処

    理を実装をする必要がなくなった 38
  40. • バリデーション – バラエティ豊富なバリデーションルール 標準ライブラリが使いやすい 39 https://readouble.com/laravel/5.5/ja/validation.html

  41. 標準ライブラリが使いやすい • テンプレートエンジン(Blade) – 覚えることが少なく、なじみやすいシンタック ス – Blade ファイルは PHP

    ファイルにコンパイルさ れ、変更が無い限りはコンパイルした PHP ファ イルを呼び出すので軽量(らしい) – 他のテンプレートエンジンとくらべ制約が緩く、 @php ディレクティブで PHP コードの記述もで きる 40
  42. 標準ライブラリが使いやすい 41 • テンプレートエンジン(Blade) – ノンフレームワークサービスの場合

  43. • テンプレートエンジン(Blade) – Laravel の場合 標準ライブラリが使いやすい 画面ごとに切替えたいコンテンツを @yield ディレクティブで指定する 42

    @section ディレクティブ内に 挿入するコンテンツを記述する
  44. 標準ライブラリが使いやすい • バッチ処理(Command) – cron レコードは 1 件、実行スケジュールを PHP 内に記述できるようになり管理が楽になっ

    た 43
  45. • バッチ処理(Command) – ノンフレームワークサービスの場合 標準ライブラリが使いやすい バージョンアップを重ねていく内に cron レコードが増えていく 44

  46. • バッチ処理(Command) – Laravel の場合 • cron は 1 レコードのみ

    • 実行スケジュールを PHP で記述できる 標準ライブラリが使いやすい 45
  47. 標準ライブラリが使いやすい • マイグレーション – DB の移行パッチの適用管理が楽になった 46

  48. • マイグレーション – ノンフレームワークサービスの場合 – Laravel の場合 アプリケーションのバージョンより、 新しいバージョンをファイル名に含 むパッチファイルを実行

    コマンドを実行するだけで、マイグ レーションファイルの中から未実行 のファイルのみを自動実行 ロールバックも可能 47 標準ライブラリが使いやすい
  49. 標準ライブラリが使いやすい • デバッグ – Laravel をバージョンアップ (5.4→5.5) 後、デ バッグモード時のエラーページの情報量がすご かった

    – デバッグ時間の大幅短縮することができた 48
  50. 標準ライブラリが使いやすい エラーメッセージ スーパーグローバル、 環境情報など スタックトレース エラー発生箇所 49 • デバッグ

  51. Laravel で良かったこと • オールインワンでスピード開発に向いていた • 簡単設定でどんなものにも繋がる • 標準ライブラリが使いやすい • ドキュメントが充実していた

    50
  52. ドキュメントが充実していた • 必要な情報が公式ドキュメントとして準備さ れていた 51 http://laravel.jp/

  53. ドキュメントが充実していた • 公式ドキュメントが日本語化されていた 52 https://readouble.com/laravel/5.5/ja/

  54. Laravel で困ったこと 53

  55. Laravel で困ったこと • Blade (SSR) + Vue.js での脆弱性 • Vue.js

    は思ったより難しかった 54
  56. Laravel で困ったこと • Blade (SSR) + Vue.js での脆弱性 • Vue.js

    は思ったより難しかった 55
  57. 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
  58. • 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 になってるんやろ?
  59. • 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 になってるんやろ? 実は、、、関係あった! (調べてよかった…)
  60. 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
  61. • 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データ レスポンス送信 ブラウザが読込
  62. • 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データ レスポンス送信 ブラウザが読込
  63. • SSR と Vue.js の組み合わせで起こる XSS – Vue.js で処理される領域にユーザー入力の文字 列を

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

    SSR で埋め込むと危険 – “mustache injection” と(個人的に)呼んで る {{…}} ← これを Mustache 構文と呼ぶことから – 知らなかったら普通に作ってしまいそう • 知らなかったし、実際作ってしまっていた Blade (SSR) + Vue.js での脆弱性 63
  65. 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') }}”
  66. 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 で処理されない
  67. Blade (SSR) + Vue.js での脆弱性 • mustache injection 対策案3 (不採用)

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

    – “{{” や “}}” の文字間に半角空白を挿入する – いつやるか? • 出力時 ⇒ “v-pre” 使用と同様の問題。対象箇所が多い・忘れ そう • 入力時 ⇒ Middleware ですべてのリクエストパラメータを処 理すれば確実 – 根本的な解決は…(^ω^; • SPA 化しかない? 68
  70. Laravel で困ったこと • Blade (SSR) + Vue.js での脆弱性 • Vue.js

    は思ったより難しかった 69
  71. Vue.js は思ったより難しかった 70 • 開発を始める前は… – チームメンバーはみな jQuery に慣れ親しんで いる(特にベテラン)

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

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

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

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

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

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

    少し複雑なことをしたいときはコンポーネン ト化が必須 – コンポーネントの考え方が分かりにくいとの声 もあるが – そこは勉強してもらうしかない
  78. まとめ 77

  79. まとめ • フレームワークがスピード開発に役立った – ミドルウェアとの連携設定 – MVC の考えに沿ったソース配置 – ビジネスロジックへの集中ができた!

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

    Laravel の豊富な機能を使いこなせない – アイデアをぜひ教えてほしいです! 79
  81. PHP エンジニア 募集中 www.facebook.com/rakus.career 80