sikaku

JavaScriptでリファラ拒否

追記(22/01/09):昨今だと条件が合致しなければリファラ全文送信しないのがデフォルト設定のブラウザが主流になってきているので、本scriptに限った話ではないですがリファラ拒否自体効果を期待しない方がいいです。

JavaScriptで行う、簡易的なリファラ拒否をしてくれる関数です。

htaccessなりPHPなりを用いてサーバー側で処理した方が当然良いですが、利用不可環境かつアクセス拒否サービスに登録をするのも面倒だったりする場合にはいいんじゃないでしょうか。

ソース覗くとそのまま「こういう拒否してるんだふーん」っていうのがばれるので作っといてなんですがあんまり使用はお勧めしません。(やるならBASE64変換して記述とか……?)

一応、アクセス拒否サービスと比較する場合、別サービスを挟まないので外部へアクセスをする時間が不要な分処理が速かったり、拒否時の処理がかなり自由なんかのメリットはあるにはあります。

source code

関数

JavaScript
  1. function refererRefusal(deny,allow,denied){
  2. var r = document.referrer;
  3. if( !check(deny) || check(allow) ) return false;
  4. if( denied ) denied();
  5. return true;
  6. function check(l){
  7. if(!Array.isArray(l)) return false;
  8. for(var i in l) if(r.match(RegExpEsc(l[i],'i'))) return true;
  9. return false;
  10. }
  11. }
  12. function RegExpEsc(str,flg){
  13. switch( Object.prototype.toString.call(str) ){
  14. case '[object RegExp]' : return str;
  15. case '[object String]' : break;
  16. default: return false;
  17. }
  18. str = str.replace(/[\-\/\|^$*+?.(){}\[\]]/g,'\x5c$&');
  19. return ( flg=='string' ) ? str : RegExp(str,flg);
  20. }

正規表現のエスケープ用関数併用

呼び出し

基本

refererRefusal(deny,allow,denied)

構文

refererRefusal([array[,array[,function]]])

refererRefusal(['siteA.com','siteB.jp'],0,function(){location.replace(r)})

引数
  • deny
    • arrayでの指定
    • 拒否したいURLリスト
  • allow
    • 基本arrayでの指定
    • 拒否URLに該当しても、許可したいURLリスト
    • 不要時はfalse0
  • denied
    • functionでの指定
    • アクセス拒否時の実行イベント
  • URLリスト
    • 配列内はstring,regexpどちらかで指定

    stringでの指定時

    大文字小文字区別なし

    部分一致

    regexpでの指定時

    記述正規表現次第

    stringでのデフォ採用一致条件以外で指定した際に採用してください。

    正規表現メモ

    正規表現エスケープ用関数も同封しているので、利用するとちょっと楽かもしれません。

戻り値
  • 拒否時:true
  • 許可時:false

呼び出し側で真偽値を見分けて拒否時許可時の処理をしてもいいかもしれません。

指定例

拒否、許可リスト

呼び出しのrefererRefusal(ここ,ここ,denied)(deny,allow部分)の記述例です。

  • リファラ取得不可時を拒否

    拒否リスト内に/^$/

    例:[/^$/,'siteA.com','siteB.jp']

  • 許可リスト内以外を拒否

    拒否リスト:[/./]

    許可リスト:['site.com']

    • site.comを含まないURLからのアクセスを拒否
    • サイトトップ以外に設置して、自サイト内以外からのアクセス拒否なんかにも使えると思います。(実質トップ経由以外でのアクセスができなくなる)

拒否時実行イベント

呼び出しのrefererRefusal(deny,allow,ここ)(denied部分)の記述例です。

ページ書き換え+自動遷移
JavaScript
  1. function(){
  2. document.addEventListener('DOMContentLoaded', function() {
  3. var tgt = document.querySelector('body');
  4. tgt.innerHTML = '禁止されたアクセスです。3秒後に自動遷移します。';
  5. });
  6. window.setTimeout(function(){
  7. location.replace('http://');
  8. }, 3000);
  9. }
調整用情報

ページ書き換え

body:書き換え対象要素の指定

禁止された...:書き換え内容の指定(HTMLタグ使用可)

:HTMLの読み込み完了次第内部処理実行という指示です。呼び出しの記述位置によっては不要(場合により発火しなくなることもある)なので、その場合は削除を。

自動遷移

http://:遷移先URL

3000:遷移までの待機時間

3000経過後内部処理実行という指示です。待機時間自体不要の場合は削除を。

location.replace()が「現ページを履歴に残さずに移動」というような処理なので、ここはlocation.href='http://'とかでもいいかもしれません。

jQuery導入済みの場合

jQuery
  1. function(){
  2. $(function(){
  3. $('body').html('禁止されたアクセスです。3秒後に自動遷移します。');
  4. });
  5. setTimeout(function(){
  6. location.replace('http://');
  7. }, 3000);
  8. }

戻り値利用での処理

戻り値が結果次第の真偽値なので、処理を引数にせずに呼び出し側でif文を使って処理をしてもいいかもしれません。

許可時のみに処理
JavaScript
  1. if( !refererRefusal(deny,allow) ){
  2. //処理
  3. }
許可リスト内での拒否リスト
JavaScript
  1. if( refererRefusal(['siteA.com','siteB.jp'],['blog']) || refererRefusal(['siteA.com/blog']) ){
  2. //処理
  3. }

「siteA.comからのアクセスは拒否したい。ブログサイトからは許可したい。その場合siteAのブログからのアクセスも通ってしまうので、それは拒否したい」的な。

これも許可リストの正規表現次第でこんなややこしい事せず済みますが一応。

demo

両方表示が変わらない場合

両方このページからのアクセスを拒否した同ページへのリンクです。

両方拒否される

通常アクセス側はrel="noreferrer"属性でリファラを渡さないようにしているだけなので、前述属性値非対応の環境だと両方から拒否されると思います。

両方通常表示

閲覧環境側でスクリプト実行拒否なりリファラ送信拒否の設定をしていると両方拒否処理自体されません。

呼び出し記述

JavaScript
  1. var deny = ['/sikaku0/blog/2/18/',/\/sikaku0\/blog\/5(\D|$)/i];
  2. refererRefusal(deny,0,function(){
  3. document.addEventListener('DOMContentLoaded', function() {
  4. var time = 3;
  5. var tgt = document.querySelector('main');
  6. tgt.innerHTML = '禁止されたアクセスです。<span id="count">'+time+'</span>秒後に自動遷移します。<i class="far fa-angry fixicon"></i>';
  7. var cnt = document.getElementById('count');
  8. setInterval(function(){
  9. cnt.innerText = --time;
  10. if( !time ) location.replace('/sikaku0/');
  11. },1000);
  12. });
  13. });