httpsサイトにhttpリソースが混在していないかPHP + Selenium WebDriverでチェックする

技術推進室の篠崎です。
httpsのサイトを運用していると知らない間にhttpリソースを読み込んでたりしている時ありませんか?
この状態で運用しているつもりが、
こんな表示になってる状態です。
広告タグとかタグ自体はhttpsリソースを指定しているんだけど内部で(APIなどから)取得するリソースはhttpだったりして、事前チェックでは防げない場合があります。
今回、httpリソースが混在しているかどうかをチェックする仕組みのサンプルをPHP + Selenium WebDriver + Chromeブラウザで作成したのでご紹介したいと思います。
※ なんでPhantomJSのようなヘッドレスブラウザ利用しないの?とかなんでPHPなの?とか疑問があるかと思いますが今回はスルーでお願いします
Chrome Developer Tools
混在しているのがわかった場合、通常Chrome Developer Toolsで確認する事が多いです。
ConsoleログにMixed Contentの警告がリソース毎に出力されるので非常に便利です。
今回はSelenium WebDriverでChromeブラウザを操作し、このConsoleログを取得、確認する事でリソースが混在しているかどうかチェックします。
試したバージョン
Chrome
- 46.0.2490.86 (64-bit)Selenium Standalone Server
- 2.48.2PHP
- 5.6.11php-webdriver
- 1.0.4
サンプル
Selenium WebDriverを利用してChromeブラウザを操作してConsoleログを取得するサンプルです。
<?php require '../vendor/autoload.php'; $host = 'http://localhost:4444/wd/hub'; $capabilities = Facebook\WebDriver\Remote\DesiredCapabilities::chrome(); // Mobile $options = new \Facebook\WebDriver\Chrome\ChromeOptions(); $options->setExperimentalOption('mobileEmulation', ['deviceName' => 'Apple iPhone 6 Plus']); $capabilities->setCapability(\Facebook\WebDriver\Chrome\ChromeOptions::CAPABILITY, $options); $driver = Facebook\WebDriver\Remote\RemoteWebDriver::create($host, $capabilities); $driver->get('確認したいURL'); $bowserLogs = $driver->manage()->getLog('browser'); foreach ($browserLogs as $browserLog) { $message = $browserLog['message']; if (preg_match('/.*Mixed Content.*/', $message)) { echo $message . PHP_EOL; } } $driver->close();
ライブラリにはFacebookのphp-webdriverを利用しています。
{ "require": { "facebook/webdriver": "1.0.4" } }
デバイス指定
デバイスを指定する事でUserAgentや画面サイズなど設定されます。
$options = new \Facebook\WebDriver\Chrome\ChromeOptions(); $options->setExperimentalOption('mobileEmulation', ['deviceName' => 'Apple iPhone 6 Plus']); $capabilities->setCapability(\Facebook\WebDriver\Chrome\ChromeOptions::CAPABILITY, $options);
アクセスログを見ると適切なUserAgentでアクセスしているのが確認できます。
Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4
Consoleログ
Log Typeにbrowserを指定する事で取得できます。
$bowserLogs = $driver->manage()->getLog('browser');
ログには以下の情報が含まれます。
- type
- message
- timestamp
httpsとhttpリソースが混在する場合は以下のようなログになります。 ※URLは適当です
Array ( [level] => WARNING [message] => https://example.com 0:0 Mixed Content: The page at 'https://example.com' was loaded over HTTPS, but requested an insecure image 'http://example.com/1.jpeg'. This content should also be served over HTTPS. [timestamp] => 1448522564149 )
例えばURLと一緒に通知するような仕組みを作ればリソース混在のチェックも自動化もできそうです。
サンプルを起動する
Selenium Standalone Serverを立ち上げます。 PHPではRubyのように直接操作できるWebDriverは提供されていないのでServer経由で操作する必要があります。 ※ php-webdriverはその処理をラップして簡単に利用できるライブラリです。
$ java -jar selenium-server-standalone-2.48.2.jar 16:13:27.839 INFO - Launching a standalone Selenium Server 16:13:27.869 INFO - Java: Oracle Corporation 25.45-b02 16:13:27.869 INFO - OS: Mac OS X 10.10.5 x86_64 16:13:27.879 INFO - v2.48.0, with Core v2.48.0. Built from revision 41bccdd 16:13:27.935 INFO - Driver provider org.openqa.selenium.ie.InternetExplorerDriver registration is skipped: registration capabilities Capabilities [{ensureCleanSession=true, browserName=internet explorer, version=, platform=WINDOWS}] does not match the current platform MAC 16:13:27.935 INFO - Driver provider org.openqa.selenium.edge.EdgeDriver registration is skipped: registration capabilities Capabilities [{browserName=MicrosoftEdge, version=, platform=WINDOWS}] does not match the current platform MAC 16:13:27.935 INFO - Driver class not found: com.opera.core.systems.OperaDriver 16:13:27.936 INFO - Driver provider com.opera.core.systems.OperaDriver is not registered 16:13:28.014 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub 16:13:28.014 INFO - Selenium Server is up and running
サンプルを実行します。
$ php sample.php
サンプルはMixed Contentという文字列が含まれていれば標準出力されます。
最後に
サーバーで自動化を検討した場合、この作りだとChromeブラウザを起動する必必要があるので仮想ディスプレイ(xvfbなど)と組み合わせが必要な分少しだけ敷居が高い(面倒)かもしれません。
ただChromeのログ取得できる事が便利なユースケースもあると思うので何かしらの参考になれば幸いです。
以上