🏙️

PHPでSVGファイルを読み込む方法(Basic認証対応) in WordPress

2022/09/17に公開約2,600字

WordPressでサイトを作っている際に、PHPファイルの中に直接SVGタグを直接埋め込むのは、
コードが長くなるので、babel-plugin-inline-react-svgのようにSVGファイルを読み込むための独自関数を作ったので、メモします

PHPでSVGファイルを読み込む独自関数

まず完成品はこちら↓

// SVGを出力する
function the_svg($path, $class = null, $style = null) {
  $context = null;
  if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
    $context = stream_context_create([
      'http' => [
        'method' => 'GET',
        'header' => 'Authorization: Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW'])
      ]
    ]);
  }

  $svg_file_path = get_theme_file_uri('/assets/svg/' . $path);
  $svg_file = file_get_contents($svg_file_path, false, $context);
  if (!$svg_file) {
    throw new Exception("Not found svg file: $svg_file_path");
  }

  $dom = new DOMDocument();
  $dom->loadXML($svg_file);
  $svg = $dom->getElementsByTagName('svg')[0];
  if (!$svg) {
    throw new Exception("Not found svg tag: $svg_file_path");
  }

  if ($class) {
    $svg->setAttribute('class', $class);
  }
  if ($style) {
    $svg->setAttribute('style', $style);
  }

  echo $dom->saveHTML();
}

補足情報

Basic認証対応

サイトにBasic認証をかけていると、file_get_contents()でSVGファイルを取得できません
そのため、認証ヘッダーを付与させるようにさせています
php.iniや.htaccessの設定、ホスティングサービスの設定によっては、
$_SERVER['PHP_AUTH_USER']$_SERVER['PHP_AUTH_PW']が取得できない場合があるのでご注意ください

$context = null;
if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
  $context = stream_context_create([
    'http' => [
      'method' => 'GET',
      'header' => 'Authorization: Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW'])
    ]
  ]);
}

php.iniのallow_url_fopenなどの設定によっては、file_get_contents()の使用時にエラーが発生する場合があるらしいので、wp_remote_get()でSVGファイルを取得する方が良いかもしれません
自分の場合はレスポンス解析が面倒で、自分がよく利用しているXserverでは特に問題がなかったため、そこは考慮していません

XSSやXXEなどの脆弱性攻撃への懸念

WordPressはデフォルトでSVGのファイルのアップロードをサポートしていません
SVGファイルはXSSやXXEなどの脆弱性攻撃の温床になるので、合理的な判断だと思います
いくらエスケープ処理を介しても色々と抜け道は出てくると思うので、、、
SVGのファイルの読み込みがデフォルトでサポートされてないのも同じような理由ではないかと勝手に思っています

https://core.trac.wordpress.org/ticket/24251

念の為、SVGファイルの読み込み場所をテーマディレクトリ下に絞っているので、
scriptタグやimgタグが埋め込まれているような危険性のあるSVGファイルを配置して読み込ませない限りは問題ないと思っていますが、セキュリティーに厚くないので、もし他の問題点やもっとセキュアなやり方をご存知でしたら教えてください

別の方法の模索

SVGInjectなどのjsのライブラリで読み込ませる方法も模索しましたが、わざわざSVGファイルを読み込ませるためだけに読み込むライブラリを増やしたくなかったため、避けました

紹介しておいてなんですが、正直あまりセキュリティ的に自信がないので、
SVGファイルをPHPファイルにラップしてコンポーネント化して、get_template_parts()でclassやstyleを引数として渡して読み込ませる方法が一番良いと思います

Discussion

ログインするとコメントできます