[wp]管理画面を除外してHTTPヘッダーを設定する手段の一つ

.htaccessは使わないほうが良さげ。

セキュリティは大事だけど設定は分けた方がいい

なぜか。

表で問題なくても裏で妙なことが起こる。投稿ページが表示されなくなったり、jsonが動かなくなったりする。そもそも必要か?と思ったり、そうでなくとも一括で指定するのは無理がある。

なので分けていく。

組み方のイメージとか概要

HTTPヘッダーはざっくり3通りの設定方法がある。

  • .htaccess
  • html:<meta>
  • php:header()

.htaccessを直下に仕込めば全てに反映されるんで、一括で済んで嬉しい。だけど今回のことが合ったので除外。

<meta>は、別にやってもいいんだけどブラウザの検証のnetworkで確認できないので作業がし辛いので除外。

ということで、header()でやる。

こんな感じ

使うのは以下

  • functions.php
  • header.php

functinos.php

こんな感じ。

<?php
add_action('after_setup_theme', function(){
    if(is_admin()) return;
    if(is_user_logged_in()) return;
    ob_start(function ($buffer_html) {
        $nonce = wp_create_nonce( 'content-security-policy' );
        $buffer_html = str_replace('<script', '<script defer nonce="'.$nonce.'"', $buffer_html);
        $buffer_html = str_replace('<style', '<style nonce="'.$nonce.'"', $buffer_html);
        return $buffer_html;
    });
}, 10000);

if(!function_exists('headerSecurity')){
    function headerSecurity(){
        if(is_admin()) return;
        if(is_user_logged_in()) return;
        $nonce = wp_create_nonce( 'content-security-policy' );
        $headerCSP = "Content-Security-Policy:";
        $headerCSP .= "default-src 'self' 'nonce-{$nonce}';";
        $headerCSP .= "script-src 'self' 'nonce-{$nonce}';";
        wp_reset_query();
        if(is_page('****')){
            $headerCSP .= "style-src 'self' * data: 'unsafe-inline';";
        }else{
            $headerCSP .= "style-src 'self' 'nonce-{$nonce}' data:;";
        }
        $headerCSP .= "connect-src 'self' https://www.google-analytics.com https://*.googleapis.com;";
        $headerCSP .= "img-src 'self' data:;";
        $headerCSP .= "font-src 'self' data:;";
        $headerCSP .= "frame-src https:;";
        $headerSecurity = header($headerCSP);
        $headerSecurity .= header("Strict-Transport-Security: max-age=31536000");
        $headerSecurity .= header("X-Content-Type-Options: nosniff");
        $headerSecurity .= header("Referrer-Policy: strict-origin-when-cross-origin");
        $headerSecurity .= header("X-Frame-Options: SAMEORIGIN");
        $headerSecurity .= header("Cache-Control: s-maxage=0, private, no-store, no-cache, must-revalidate");
        $headerSecurity .= header("X-Permitted-Cross-Domain-Policies: none");
        $headerSecurity .= header("Access-Control-Allow-Origin: https://code.jquery.com https://secure.gravatar.com https://firebase.googleapis.com ");
    }
}

ページ別の条件分岐を作る場合、関数(function)に格納する必要がある。本当はグローバル変数で済ませたいけど、WPの作法に沿う必要がある。めんどくさいけどこれにより、ページ別の条件分岐が使えるようになる。というか、そもそもの前提で必須。

不要な環境はreturn;でスキップさせる。is_admin()で管理画面を除外する他、ログイン状態(is_user_logged_in())も除外する必要がある。そうしないと投稿ページの保存時にJSON周りでエラーを吐く。セキュリティよりもまずは実働優先。なので、HTTPヘッダーが設定できてるかどうかの確認はログインしてない環境で見てください。orにすればいいんだけどなんとなく分けてみた。

で、内容的な条件で言えば、例えば、現行のWPの投稿本文の装飾はstyle属性を使う事があるのでstyle-srcに’unsafe-inline’を仕込む必要がある。全体に反映させると無駄にセキュリティを下げるだけなので、is_single()で振り分けたりページ単位でピンポイントに指定することができるという訳。

今回のHTTPヘッダーはイメージなんで、ちゃんとした設定内容は別で補完してください。

header.php

コードの一番上にこんな感じで仕込む。

<?php
if( function_exists('headerSecurity')){
    headerSecurity();
}
?>

header()は仕様上、手前にタグがあるとエラーを吐くから一番初めに書かないといけないっていう、PHPの仕様。

まとめ

セキュリティなんて今まで触れてこなかったんでかなり厄介。

しかもいきなりWPにぶっこむもんだから、どういうアレで何になってるかもぶっつけで調べていくしか無いっていうね。

それはそれとして、header()をfunctions.phpで直接仕込めたらいいんだけど、設置場所はwp_head()のところですよね多分。<head>の中に書かれるからwpタグで挿入するとエラーになる。ここが一発でできるならheader.phpを編集する必要がなくて助かるんですけどね。

コメント

タイトルとURLをコピーしました