リバースプロキシ環境で結構ハマったのでブログにします。結論から書くと、WordPressのドキュメントに
Note: FORCE_SSL_ADMIN should be set before wp-settings.php is required.
wp-settings.phpを読み込む前にFORCE_SSL_ADMINは定義しなければならない、と書いてありますがSSL関係の設定は全てこれの前に書かないと動作しません。
HTTPS化でFAQだと思われる所でハマる
リバースプロキシ環境のこのブログ ( https://blog.ohgaki.net ) をHTTPS化したら、設定ページのサイトURLを http:// から https:// にすると管理者ページに一切アクセスできなくなりました。
このページにアクセスする権限がありません。
環境:
- OS: CentOS 7 (リバースプロキシ、Webサーバー両方)
- リバースプロキシ: Nginx 1.10.1 (CentOS7パッケージ)
- Webサーバー:Apache 2.4.6 (CentOS7パッケージ)
- PHP: PHP 7.1.0RC3 (remi-php71パッケージ)
ネットで検索すると「リダイレクトでループするので、wp-config.phpで$_SERVER[‘HTTPS’]=onに設定すれば良い」と直ぐ見つかります。
実際、$_SERVER[‘HTTPS’]=onを記述するとリダイレクトループは無くなるのですが、管理ページ全てが
このページにアクセスする権限がありません。
と表示されて使い物になりません。
散々やってみたり、バグかと思ってみたりしたのですが、やはり自分の設定が悪いようです。結局、正しく動作したのは以下のようなwp-config.phpでした。
/** Absolute path to the WordPress directory. */ if ( !defined('ABSPATH') ) define('ABSPATH', dirname(__FILE__) . '/'); /** SSL Support **/ function isSecure() { if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { $_SERVER['HTTPS'] = 'on'; return TRUE; } return FALSE; } $web_site = 'blog.ohgaki.net'; $schema = isSecure() ? 'https://' : 'http://'; $web_site_url = $schema . $web_site; define('WP_HOME', $web_site_url); define('WP_SITEURL', $web_site_url); define('FORCE_SSL_LOGIN', true); define('FORCE_SSL_ADMIN', true); /** Sets up WordPress vars and included files. */ require_once(ABSPATH . 'wp-settings.php');
間違っていたのは、
require_once(ABSPATH . 'wp-settings.php');
の前に設定する、つまりSSL関係の設定はwp-settings.phpを読み込む前に設定用の定数と変数を定義しなければならない、という所でした。
こういう設定ファイルなどでは、自分が明示的に設定したい値をいつも最後に記述していた+中途半端にリダイレクトループだけが解消されたので、この間違いに気がつくまでに随分時間を無駄にしました。
他の方が同じように無駄な時間を消費しないように、間違いを公開しておきます。
HTTPS化に便利なupgrade-insecure-requests
HTTPS化できたのは良いのですが、コンテンツにも http:// で始まるURLが900以上ありました。全て置換しても良いのですが、nginxの設定に
add_header Content-Security-Policy upgrade-insecure-requests;
を付け加えました。こうすると今どきのChrome, Firefox, Safari, Edgeでは http:// で始まる場合に自動的にhttps://に変換してリクエストしてくれます。http:// で始まる画像やCSS、JavaScriptがあってもSSLのグリーンマークが付きます。
今日はもうWordPressを触ることに関して満腹なのでこれで良しととします。
その内に置換するかも知れませんが、変換漏れなどがあった場合でもupgrade-insecure-requestsが在れば、今時のブラウザならエラーにならないので入れておいた方がよいと思います。
最初、サイトURLの変更はせずにhttp://のままで、upgrade-insecure-requestsを追加しただけで動かしました。ほとんどの機能は使えたのですが、この設定だとJetPackの管理ページが一部使えなかったり、GoogleのAdSenseプラグインの設定ページが真っ白になったりしました。サイトURLをhttps:// にするとこれらの問題は解消しました。
HTTPSでもリファラーを有効に
HTTPS化して困るのはリファラー(どのページから遷移したか、ブラウザーに設定されるHTTPリクエストヘッダー)です。HTTPSだとリファラーが設定されません。これに対する対策はW3Cで検討中です。最新版は以下で参照できます。
- http://www.w3.org/TR/referrer-policy/(W3C草案)
- https://w3c.github.io/webappsec/specs/referrer-policy/(編集者草案)
metaタグやaタグでも設定できますが、Webサーバーのレスポンスヘッダーを設定できるなら、Webサーバー設定で変更するのが簡単です。このブログの場合、全てのサイトにリファラーを送っても構わないので、nginxの設定に以下を追加しました。
add_header Referrer-Policy unsafe-url;
まだ確定仕様でないので変更があると思いますが、主要な部分はほぼ現在のままだと思います。
その他のPHP 7.1の問題
この問題の他にも、関数パラメーターにオブジェクトを渡すコードに不必要な参照が利用されている場合、Warningエラーが発生する箇所がありました。これは
diff -ur wordpress/wp-includes/script-loader.php html/wp-includes/script-loader.php --- wordpress/wp-includes/script-loader.php 2016-09-01 08:13:30.000000000 +0900 +++ html/wp-includes/script-loader.php 2016-10-08 15:54:06.412026989 +0900 @@ -42,7 +42,7 @@ * * @param WP_Scripts $scripts WP_Scripts object. */ -function wp_default_scripts( &$scripts ) { +function wp_default_scripts( $scripts ) { include( ABSPATH . WPINC . '/version.php' ); // include an unmodified $wp_version $develop_src = false !== strpos( $wp_version, '-src' ); @@ -752,7 +752,7 @@ * * @param WP_Styles $styles */ -function wp_default_styles( &$styles ) { +function wp_default_styles( $styles ) { include( ABSPATH . WPINC . '/version.php' ); // include an unmodified $wp_version if ( ! defined( 'SCRIPT_DEBUG' ) )
のような感じで修正すると直ります。1 PHP 5.6でも同様のコードでWarningが1つ発生するのですが、PHP7.xの場合は追加で発生するエラーが表示されてしまう(?)ようです。
まだあまり使っていないので何とも言い難い+今はRCなので当然ですが、WordpPress + PHP 7.1 で利用する場合は、期待通りに動作するかよく確認してから移行する方がよいです。このブログは何かあっても最悪、しばらく止まってもOK、自力で解消するつもりだったのでテスト無しに移行してしまいました ;)
- これはPHP 7.0.11でも発生します。一応、PHPのバグとしてレポートはしてありますが、そもそもPHP5以降の場合、オブジェクトをリファレンスにする必要がないのでWordPressのコードを直す方が良いと思います。 ↩