茶番
「どうも〜、セミコロンつけない派です。お願いします」
「お願いします」
「あ〜、ありがとうございます。今、LGTMを頂きました。こんなんなんぼあってもいいですからね」
「あのな、おかんがな、思い出せない都道府県があるらしいねん」
「ほな、その特徴教えてくれる?」
「おかんが言うにはな、最近ゲームが
「香川やないか!」
(ミルクボーイやりたかっただけ。)
ちまたで噂のネット・ゲーム依存症対策条例
ネットやゲーム依存症を防ぐため、18歳未満の使用時間を制限するというやつです。
今はちょっと変わってコンピュータゲームだけになったみたいです。
これに関する議論は尽きないですが、ここでは置いておきます。
仮にサービス側が何とかしろと言われたら...
ネット界隈では、「香川県民ですか? はい/いいえ」のような香川認証がネタになってます。
香川県の条例案、よく読んだら我々サービス提供者側(特定電気通信役務提供者)も県民が「ネット・ゲーム依存症」に陥らないように必要な対策を実施しなくちゃいけないらしい。
— 佐藤大哲-DaitetsuSato@地学オリンピック中の人 (@SatoDaitetsu) 2020年1月21日
これ、つまりサービス提供時に「あなたは香川県民ですか?」とか聞いてYesと言ったら時間制限つけるみたいな話になるぞ。 pic.twitter.com/TtOdC9LDqa
しかし、本当にサービス側が対策しないと行けなくなったらやばい。(絶対ないと思うけど)
そこで、JavaScriptのGeolocation APIを使って香川からのアクセスを避けてみます。
ソースコードはこちらにあります。
香川ブロックプログラム
概略
回避法としては下の図のようになります。
Geolocation APIで緯度経度を取得し、逆ジオコーティングAPIで都道府県を割り出し、香川県だった場合はブロックします。
今回は簡易的に香川県だった場合は、香川県のホームページに飛ばします。
メインの部分は以下の感じです。
document.addEventListener('DOMContentLoaded', async () => {
const message_id = document.getElementById('message')
// 位置情報取得対応かチェック
if (navigator.geolocation) {
// 現在位置をPromiseとして取得 - (1)
const postion = await getCurrentPositionAsPromise().catch(error => {
console.log(error)
message_id.innerHTML = '現在位置を取得できませんでした'
})
// 逆ジオコーディングにかける - (2)
const json = await getPrefecture(postion.coords.latitude, postion.coords.longitude).catch(error => {
console.log(error)
message_id.innerHTML = '都道府県を特定できませんでした'
})
const prefecuture = json.result.prefecture.pname
// 香川県なら県のホームページへ
if (prefecuture === '香川県') {
location.href = 'https://www.pref.kagawa.lg.jp/'
} else {
message_id.innerHTML = 'ようこそ'
}
} else {
message_id.innerHTML = '位置情報取得を許可してください'
}
})
(1) 位置情報取得
Geolocation APIは、getCurrenctPosition(successFunc, errorFunc, options)
で現在位置を取得することができます。
ただし、位置情報取得は許可されてる時のみです。
また、この許可をポップアップによって求めることがあるのですが、この応答待ちが必要なので、Promise
で包みます。
async function getCurrentPositionAsPromise() {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject)
})
}
(2) 都道府県情報照合
Geolocation APIで取得した位置情報を逆ジオコーディングAPIにかけます。
位置情報はgetCurrentPosition()
の返り値をposition
とすると、
緯度: position.coords.latitude
経度: position.coords.longitude
で受け取れます。
逆ジオコーディングにはfinds.jsの簡易逆ジオコーディングサービスを使いました。
APIキー取得が不要で使いやすいです。
APIにはfetch
を使って投げます。
ここも取得待ちが必要なので、fetch
をそのままPromise
として返します。
const API_URL = 'http://www.finds.jp/ws/rgeocode.php'
async function getPrefecture(latitude, longitude) {
const response = await fetch(`${API_URL}?json&lat=${latitude}&lon=${longitude}`,{
mode: 'cors'
})
if (response.ok) {
return response.json()
} else {
throw new Error(`${response.status}: ${response.statusText}`)
}
}
注意
このプログラムを動かす時、Web APIを使ってるためCORS要求がうまくいかず、失敗する場合があります。
Chromeだと、拡張機能としてMoesif Origin&CORS Changerを入れるとなんとかできる場合があります。
あと位置情報取得にもAPIの応答待ちも少し時間がかかるため、待つ必要があります。
位置偽造実験
香川県にいないので、実際に香川からアクセスした場合の挙動がわかりません。
なので、Chromeの機能を使って位置情報を香川県に変更します。
香川県の高松市の緯度経度を使用します。
結果、無事香川県のホームページに飛ばされました。
位置情報変えられるのであれば、香川県からのアクセスを別のところからにもできますが(笑)。
まとめ
今回はGeolocation APIを使って香川県からアクセスされた場合、ブロックしてみました。
というか、香川県のゲーム規制をネタにGeolocation APIで遊んでみました。
実際、ゲーム規制どうなるんですかね。
記事執筆段階では、親に努力義務が課せられるという状態ですが、果たして。
(追記)
*1: @alt さんがタグを修正して下さいました。
*2: @proudust さんがasync/await
で書き換えて下さいました。
*3: @yukiyukki さんがエラー修正してくださいました。
ありがとうございます。
(追記2)
ねとらぼさんでこの記事を取り上げて頂きました。
よろしければ、ご一読ください。
「香川県からのアクセスをブロックするプログラム」が話題に ネット・ゲーム依存症対策条例への問題提起として
(追記3)
いいねをLGTMに変更しました。
参考文献
Geolocation APIをPromiseでラップして扱う(TypeScript)
簡易逆ジオコーディングサービス
Moesif Origin&CORS Changer
ローカルのHTMLファイルでfetchを試す & CORSとその回避策
【Google Chrome】位置情報を変更してPCの現在地を自由自在に設定
香川県の市町村ごとの緯度経度一覧