956
367

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.

もしものために,香川県からのアクセスを避ける

Last updated at Posted at 2020-01-22

茶番

「どうも〜、セミコロンつけない派です。お願いします」
「お願いします」
「あ〜、ありがとうございます。今、LGTMを頂きました。こんなんなんぼあってもいいですからね」

「あのな、おかんがな、思い出せない都道府県があるらしいねん」
「ほな、その特徴教えてくれる?」
「おかんが言うにはな、最近ゲームが

「香川やないか!」

(ミルクボーイやりたかっただけ。)

ちまたで噂のネット・ゲーム依存症対策条例

ネットやゲーム依存症を防ぐため、18歳未満の使用時間を制限するというやつです。
今はちょっと変わってコンピュータゲームだけになったみたいです。
これに関する議論は尽きないですが、ここでは置いておきます。

仮にサービス側が何とかしろと言われたら...

ネット界隈では、「香川県民ですか? はい/いいえ」のような香川認証がネタになってます。

しかし、本当にサービス側が対策しないと行けなくなったらやばい。(絶対ないと思うけど)

そこで、JavaScriptのGeolocation APIを使って香川からのアクセスを避けてみます。

ソースコードはこちらにあります。

香川ブロックプログラム

概略

回避法としては下の図のようになります。

Geolocation APIで緯度経度を取得し、逆ジオコーティングAPIで都道府県を割り出し、香川県だった場合はブロックします。
今回は簡易的に香川県だった場合は、香川県のホームページに飛ばします。
メインの部分は以下の感じです。

index.js
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で包みます。

index.js
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として返します。

index.js
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の現在地を自由自在に設定
香川県の市町村ごとの緯度経度一覧

956
367
18

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
956
367

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?