1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

htaccessが動かない(リファラ制限)

Last updated at Posted at 2021-10-01

リファラ制限を設定したhtaccessファイルを設置しているのに、所定のURLから遷移した際閲覧できない不具合が発生していた(ChromeとEdgeのみ)。大きな範囲から検証していく。
(IPアドレス制限も記述に含んでいるが今回検証範囲ではないので説明は割愛)

SetEnvIf Referer "^http[s]*://~~~~~~~~" chk_url

order deny,allow
deny from all
allow from env=chk_url
allow from XXX.XXX.XXX.XXX

###前提
開発環境で本番のリファラを設定するわけにもいかないので、開発環境内同士でリファラを設定し検証していた。その時点では問題なし。

###リファラ元HTMLのチェック

  • aタグリンク先のURLをスラッシュで終わる形に修正
  • キャッシュ削除

☞意味なし。

###そもそも
特定のブラウザでのみ発生する不具合……ということで、(嫌な予感)「リファラ ブラウザ対応」で検索する

https://www.rectus.co.jp/archives/964
Chromeはver.85以降、Edgeはver.86時点、Safariは14.0.1 604.1時点で参照元がトップページレベルでしか取得できなくなっている とのこと。セキュリティ対策らしい。

マークアップ側はブラウザ対応について逐一調べて使用しているけど、リファラは盲点だった……💀

###対策(ブラウザ対応)
3種類ある。1つめはリファラを受け取る側で可能な設定、後の2つはリファラを渡す側で可能な設定となるので注意。
1つはhtaccessのリファラ元の設定を個別のページからTOPページ(ルートレベル)に変更する方法。構造上支障がないかは要確認。

SetEnvIf Referer "^http[s]*://~~~~~~~~/test/test/top.html" chk_url
☟
SetEnvIf Referer "^http[s]*://~~~~~~~~/" chk_url

もう1つは遷移元のaタグに従来のリファラを渡すよう、rel属性を記述する方法。

<a href="https://~~~~~~/" rel="no-referrer-when-downgrade">設置ページへ</a>

最後1つは遷移元ページのhtaccessに従来のリファラを渡すよう、命令を記述する方法。

<IfModule mod_headers.c>
Header set "Referrer-Policy" "no-referrer-when-downgrade"
</IfModule>

これでリファラ制限の不具合は解消されたが、所定ディレクトリ内での遷移(たとえばpdfファイルを開くなど)は403エラーになる。
これはhtaccessが設置ディレクトリ以下ですべて効いているため、対象ファイルへの遷移時にも同一のリファラ制限が効いてしまうことによる。

###対策(同ディレクトリ内遷移)
2つある。
1つは対象ファイルを別ディレクトリに設置し、htaccessの影響範囲の外に出す方法。
注意点は、アクセス制限の外に置かれるため、URLさえ知っていれば移動後の対象ファイルに誰でもアクセス可能なことがある。

もう1つはhtaccessのリファラ元URLに、遷移先のトップページを追加する方法。
トップページをリファラ元に設定しても支障ないか構造の確認が必要。

SetEnvIf Referer "^http[s]*://~~~~~~~~" chk_url
SetEnvIf Referer "^http[s]*://~~~~~~~~" chk_url ☜遷移先のトップページを追加

このほか、特定のディレクトリのみアクセス制限を解除する…という解決法もありそうだが、ややこしいわりにセキュリティ面では1つめと同様不安が残るので割愛。

###それにしても
開発環境の段階でリファラの不具合を発見できればよかったのに、なんで動いてたんだ。Chromeも同じver.85以降だったのに……と思っていたけど、Referrer-Policyはオリジンが同一か別物かで挙動がだいぶ変わってくるらしい。それこそhtaccessに特別な指定のない限り「同一オリジン間でリクエストを行う場合はオリジン、パス、クエリ文字列を送信」するようになっているようだ。
以下はReferrer-Policyのドキュメント。オリジンごとの挙動などが記載してある。
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Referrer-Policy
Referrer-Policyの解説記事は以下
https://qiita.com/n3_x/items/c2bafd5872af61147c89

検証したければ、リファラはブラウザのconsoleで以下コードを入力すれば確認できる。
https://www.nishishi.com/javascript-tips/encodeuri.html

alert( document.referrer );

あるいはChrome検証のNetworkタブを開くと、各通信ごとのRequest HeadersやGeneralの欄でreferrerの情報が確認できる。

どちらにせよReferrer-Policyに関する十分な知識のない限り、開発環境の検証では発見できなかったミスといえる。ヨボボ

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?