@bockring

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

JSのデバイスフィンガープリントが重なりすぎる

解決したいこと

Webブラウザ上で利用可能な投票サービスにおいて,重複投票を禁止するためのデバイスフィンガープリント認証がバグること.

発生している問題・エラー

投票を実行しているデバイス上で,まだ投票をしていないのに「投票済み」と表示され,サービス利用ができないこと.

私の学校のクラスで試験導入し,その半数のアンケート結果によると半数が投票できていない状況でした.そしてアンケートに答えていない人も含めると投票できた人は39人中の15人しかいなかったです.

投票できない,というのは以下のような画面のことを指します.
IMG_0722.jpeg

該当するソースコード

fingerprint.jsのコードをGitHub上から表示しておきます.

デバイスフィンガープリントに使用している情報は以下の10種類です.

  • User Agent
  • 言語
  • 画面解像度
  • タイムゾーン
  • プラットフォーム
  • CPUコア数
  • デバイスメモリ
  • タッチサポート
  • Canvasフィンガープリント
  • WebGLフィンガープリント

これらの10種類は,そうそう重ならない物だと思っていたのですが,同種の端末だからか重なってしまったのかもしれません.

自分で試したこと

フィンガープリントと共に使用しているCookie認証の緩和

重要な補足

このサービスは学校で使っている物であって,製との端末は全て一緒です.CPUコア数や画面解像度,言語,タイムゾーン等の情報が揃いやすく,そのうえOSバージョンも揃いやすい状況です.

そのような状況でも他の人のデバイスと重なりにくいフィンガープリント情報を教えていただけると助かります.


またデバイスフィンガープリントの情報はGoogle Firebase Realtime Detabase上でリストデータとして格納しています.そのデータがリセットされる(=投票数がゼロになる)とスレーブも再読み込みをかけ投票ブロック状態を解除します.解除(リセット)はマスターでかけるためCookieの利用はバグの元であることは既に確認済みです.

クローズ

みなさまご回答ありがとうございました.結局,LocalStorageを用いて投票記録を残し,ローカルストレージの記録を優先する仕様に変更しました.一応動いてるように見えるのでクローズさせていただきます.

0 likes

3Answer

既に他の方が回答していますが、重複を完璧に防ぐことは出来ません。
許容範囲を決めてユニークIDやトークンなどを発行した方が良いでしょう。

あと

悪用されて多額の費用を請求されても良いなら聞き流して構いませんが、vote.jsに書かれているapiキーを大っぴらに公開しない
そもそもキーをソースに直接書かないか、git側で工夫する。

もし、キーが本物なら変更した方が宜しいでしょう。

2Like

Comments

  1. @bockring

    Questioner

    ご回答ありがとうございます.

    APIキーの問題は把握しているのですが,Node.jsなどの使い方が分からなくて足踏み状態,という感じです.gitignoreの使い方もあまりわかっていない状態で,どのようにすれば解決できるか教えていただけると助かります.

  2. コンフィグを環境変数に移して環境変数からキーを呼び出せば良いことです。

    なおgit側は更新をかけても差分を見るとバレるので、簡単な方法としては一度破棄するかプライベートに変える。

  3. @bockring

    Questioner

    ありがとうございます.参考にさせていただきます.

投票後にlocalStorageやCookieにデータを入れればよいのではないでしょうか?

1Like

Comments

  1. @bockring

    Questioner

    ご回答ありがとうございます.
    当初はCookieにも認証データを格納していたのですが,「どちらかに投票済みデータが存在すれば投票ブロック」というルールの場合はFirebase上でのデバイスフィンガープリントのリストデータ削除後もCookie認証ではじかれ投票できないという問題に直面しました.このシステムではFirebaseに最も正しいとされる認証情報が書き込まれているため,逆に「Firebaseの投票ステータスにあわせてCookieを変更」にするとCookieの意味は無くなります.
    よってCookieやデバイスストレージを用いたサブ認証はしていません.

    マスターから投票ブロック状態を解除する必要があるのです.

学校のような全く同じ機器を揃えて導入しているような環境でfingerprintを使ったら当然同じ結果になりますよね、としか言えません。

解決方法はいくつかあると思いますが一つの例として書いてみます。

・投票画面にアクセスした際に、vote_tokenという名前のCookieを持っていなければ、「各学生毎に重複しない、かつ予測困難であるランダムな文字列」を内容に持つvote_tokenという名前のCookieを発行する。
vote_tokenという名前のCookieを既に持っている場合、その内容と投票済みフラグが既にDBに書き込まれていたら投票済みと判断する。
・投票完了時にDBにvote_tokenの内容と投票済みフラグを一緒に書き込む。
・リモート側で投票状況をリセットしたい場合は投票済みフラグを一律falseにする。

ブラウザを変えた場合やCookieを手動で変更・削除した場合は何度も投票できてしまう問題がありますが、これはfingerprintを利用する場合も同様の問題を抱えていますので許容できるものと想定しています。
もしこれを許容しない場合は他のやり方をする必要がありますが学生さんのようですのでぜひ考えてみてください。

1Like

Comments

  1. @bockring

    Questioner

    ご回答ありがとうございます.

    確かにCookieの認証方式を変更するのは良い案だと思います.既存のデバイスフィンガープリント認証とともに利用する認証として実装しようと思います.デバイスフィンガープリントの方でも総デバイス数の半数ほどは正しく認証できていたため,Cookie追加の形式を取ろうと思います.

  2. @bockring

    Questioner

    追記します.

    少しCookieの仕様を変更してみました.投票ボタンを押したタイミングでCookie記録する点に変更はないですが,vote.js内にある表示リセットのコードにCookieクリアを追加し,CookieとFirebaseの両方のデータが未投票状態でないと投票できない仕様にしてみました.教えていただいた方法とは少し違いますが参考になりました.ありがとうございます.

  3. そもそもfingerprintは「サードパーティcookieを利用できない状況でどうにかしてユーザーをトラッキングできないか」という思惑のあるターゲット広告などが苦肉の策で利用するもので、精度は高くなく、今回のような「同一サイト内で」「ユーザーを(ある程度)正確に見極めたい」場合に利用する技術ではありません。
    https://www.videor.co.jp/digestplus/article/41277.html

    あと他の方からの指摘にもありましたが、もし記載されているAPIキーが本物なら悪用される恐れがあります。
    ダミーならその旨記載するか、本物なら質問ごと削除してしまい、改めて立て直した方がいいかなと思います。
    (Qiitaは編集履歴が残ってしまい他の人からも閲覧できてしまうので)

  4. @bockring

    Questioner

    GitHubから抜いているので本物ですね.

    質問をクローズして削除してから変更しておきます.

Your answer might help someone💌