JavaScriptでリファラ拒否
- 追記
- 関数内処理調整(拒否時イベントの呼び出しを
denied.call()
からdenied()
へ変更) - 記事再掲(処理も変更)
- 記事公開
追記(22/01/09):昨今だと条件が合致しなければリファラ全文送信しないのがデフォルト設定のブラウザが主流になってきているので、本scriptに限った話ではないですがプロトコル+ドメイン部分以外でのリファラ拒否自体効果を期待しない方がいいです。
JavaScriptで行う、簡易的なリファラ拒否をしてくれる関数です。
htaccessなりPHPなりを用いてサーバー側で処理した方が当然良いですが、利用不可環境かつアクセス拒否サービスに登録をするのも面倒だったりする場合にはいいんじゃないでしょうか。
ソース覗くとそのまま「こういう拒否してるんだふーん」というのが丸わかりなので作っといてなんですがあんまり使用はお勧めしません。(やるならBASE64記述で多少難読化とか……?)
一応、アクセス拒否サービスと比較する場合、別サービスを挟まないので外部へアクセスをする時間が不要な分処理が速かったり、拒否時の処理がかなり自由なんかのメリットはあるにはあります。
source code
関数
JavaScript
- function refererRefusal(deny,allow,denied){
- var r = document.referrer;
- if( !check(deny) || check(allow) ) return false;
- if( denied ) denied();
- return true;
- function check(l){
- if(!Array.isArray(l)) return false;
- for(var i in l) if(r.match(RegExpEsc(l[i],'i'))) return true;
- return false;
- }
- }
- function RegExpEsc(str,flg){
- switch( Object.prototype.toString.call(str) ){
- case '[object RegExp]' : return str;
- case '[object String]' : break;
- default: return false;
- }
- str = str.replace(/[\-\/\|^$*+?.(){}\[\]]/g,'\x5c$&');
- return ( flg=='string' ) ? str : RegExp(str,flg);
- }
呼び出し
基本
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リスト
- 不要時は
false
0
等
-
denied
- functionでの指定
- アクセス拒否時の実行イベント
-
URLリスト
- 配列内はstring,regexpどちらかで指定
▽
大文字小文字区別なし
部分一致
▽
戻り値
- 拒否時:
true
- 許可時:
false
呼び出し側で真偽値を見分けて拒否時許可時の処理をしてもいいかもしれません。
指定例
拒否、許可リスト
呼び出しのrefererRefusal(ここ,ここ,denied)
(deny
,allow
部分)の記述例です。
-
リファラ取得不可時を拒否
拒否リスト内に
/^$/
例:
[/^$/,'siteA.com','siteB.jp']
-
許可リスト内以外を拒否
拒否リスト:
[/./]
許可リスト:
['site.com']
- site.comを含まないURLからのアクセスを拒否
- サイトトップ以外に設置して、自サイト内以外からのアクセス拒否なんかにも使えると思います。(実質トップ経由以外でのアクセスができなくなる)
拒否時実行イベント
呼び出しのrefererRefusal(deny,allow,ここ)
(denied
部分)の記述例です。
ページ書き換え+自動遷移
JavaScript
- function(){
- document.addEventListener('DOMContentLoaded', function() {
- var tgt = document.querySelector('body');
- tgt.innerHTML = '禁止されたアクセスです。3秒後に自動遷移します。';
- });
- window.setTimeout(function(){
- location.replace('http://');
- }, 3000);
- }
▽ページ書き換え
body
:書き換え対象要素の指定
禁止された...
:書き換え内容の指定(HTMLタグ使用可)
:HTMLの読み込み完了次第内部処理実行という指示です。呼び出しの記述位置によっては不要(場合により発火しなくなることもある)なので、その場合は削除を。
▽自動遷移
http://
:遷移先URL
3000
:遷移までの待機時間
:3000
経過後内部処理実行という指示です。待機時間自体不要の場合は削除を。
:location.replace()
が「現ページを履歴に残さずに移動」というような処理なので、ここはlocation.href='http://'
とかでもいいかもしれません。
jQuery
- function(){
- $(function(){
- $('body').html('禁止されたアクセスです。3秒後に自動遷移します。');
- });
- setTimeout(function(){
- location.replace('http://');
- }, 3000);
- }
戻り値利用での処理
戻り値が結果次第の真偽値なので、処理を引数にせずに呼び出し側でif文を使って処理をしてもいいかもしれません。
許可時のみに処理
JavaScript
- if( !refererRefusal(deny,allow) ){
- //処理
- }
許可リスト内での拒否リスト
JavaScript
- if( refererRefusal(['siteA.com','siteB.jp'],['blog']) || refererRefusal(['siteA.com/blog']) ){
- //処理
- }
「siteA.comからのアクセスは拒否したい。ブログサイトからは許可したい。その場合siteAのブログからのアクセスも通ってしまうので、それは拒否したい」的な。
これも許可リストの正規表現次第でこんなややこしい事せず済みますが一応。
demo
呼び出し記述
JavaScript
- var deny = ['/sikaku0/blog/2/18/',/\/sikaku0\/blog\/5(\D|$)/i];
- refererRefusal(deny,0,function(){
- document.addEventListener('DOMContentLoaded', function() {
- var time = 3;
- var tgt = document.querySelector('main');
- tgt.innerHTML = '禁止されたアクセスです。<span id="count">'+time+'</span>秒後に自動遷移します。<i class="far fa-angry fixicon"></i>';
- var cnt = document.getElementById('count');
- setInterval(function(){
- cnt.innerText = --time;
- if( !time ) location.replace('/sikaku0/');
- },1000);
- });
- });