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

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ログを取得、確認する事でリソースが混在しているかどうかチェックします。

試したバージョン

サンプル

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のログ取得できる事が便利なユースケースもあると思うので何かしらの参考になれば幸いです。

以上


名無しのエンジニア
角煮botはじめました
MySQLで日本語全文検索ができるMroongaのDockerリポジトリーをメンテナンスしています