質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • PHP

    20256questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    16326questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • SQL

    2377questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

  • Cookie

    176questions

    HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。

PHP,Javascriptで1人1回のみ投票できるような機能を実装したいのですが

解決済

回答 5

投稿

  • 評価
  • クリップ 7
  • VIEW 1,964

gucha

score 32

前提・実現したいこと

ウェブページで1人1回のみ投票できるような機能を作ろうとJavascriptとPHPで構成を考えたのですが
上手く制御する方法が思いつかないので質問します。

投票する項目は動的に増加していくものを想定しています。
データベースには投票の結果のみを記録しクライアントの情報などその他の情報は、
データ量節約の為に保存しないようにしたいです。
ユーザーへの負担を減らす為にもアカウント登録制なども避けたいです。

発生している問題・エラーメッセージ

PHPにPOSTでデータを送りPHPからデータベースへPOSTされたデータを保存する所までは作りました。
次に1人1回までという制限を作ろうと考えたのですが、POSTデータを覗かれると意図的にそのデータを作成してPHPに投げることができると気付いたので、上手く制御する方法が思いつきません。

たとえlocalstorageやcookieでPHPに渡すプログラムを制御したとしても最初に通すPOSTデータをコピーしてそのまま通せば何度でも通ってしまうと考えています。
データベースを消費して照合させる方法などは思いつくのですが容量削減の為に断念しました。

POSTの中身を覗かれないような方法があれば一番良いと考えているのですがそのような方法はありますか?
また皆様でしたら、登録制なしでデータベースには結果のみ保存という条件で1人1回の制限を実装するにはどのような方法を考えますか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+25

  1. 既に投票したIPアドレスからの投票を拒否する。
  2. Cookieでの制限をする。
  3. ユーザーエージェントで判断する。

以上の3点だけで通常は投票回数を制限するには事足りると思います(例外ももちろんありますが)。
あとは、悪意のある利用者に対する対策を行うと良いと思います。以下に例を挙げておきます。

  • reCAPTCHAを使う。
  • Proxy経由での投票を拒否する。
  • 海外ホストからの投票拒否。
  • CSRF対策, Refererの判定。

個人的には、IPアドレスによる制限とreCAPTCHAの導入を推奨しますが、IPアドレスの制限に関してはNATやProxyで複数IPを束ねている場合などに投票が正しくできない事態が発生するので、導入するときには注意するべきだと思います。
また、実際はこれだけ対策しても1人1回のみの投票を実現することはできません(ほぼ不可能だと思います)。しかし、不正な投票の割合は対策を怠っていた場合よりも減ると思うので、やっておくにこしたことはありません。
Webアプリケーションのセキュリティに関連する色々なことはここに載っているので、一度みてみると参考になるかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/25 09:33

    > 既に投票したIPアドレスからの投票を拒否する。
    これ、一般的で善良な利用者も投稿を制限される可能性がありますよ。
    たとえば、学校で隣り合った人同士が投稿しようとしたとして、片方は投稿できて片方は投稿できないといったことが発生します。

    キャンセル

  • 2017/01/25 10:31

    te2jiさんの指摘されたとおり、グローバルIPアドレスを共有しているような環境ではIPアドレスによる制限を行うと正常に投票が行えなくなってしまうことを考慮していませんでした。修正させていただきました。失礼しました。

    キャンセル

  • 2017/01/25 10:49

    もう一声言うと、Proxy もですね。NATだけでなく、Proxy でも IP アドレスは束ねられてしまいます。
    回答にある Proxy は公開 Proxy のことだと思うので、その辺も追記されたほうが良いかと。

    キャンセル

  • 2017/01/25 11:01

    なるほど。確かにそのとおりですね。指摘していただいた2点の追記をさせていただきました。

    キャンセル

+9

s8_chuさんの回答の通りで、
ユーザアカウント、個人情報を登録しない以上は、
厳密に1人1回のみの投票の仕組みを担保するのは不可能と考えるべきです。

イントラネット利用ならともかく、インターネットの世界ではありとあらゆるネットワーク構成を考慮しなければなりません。

例えばIPアドレスベースの判定をしたとしても、
利用者端末が1つのグローバルIPに対応付けたNAPTを挟む構成であればアウトです。
(※NAPTを挟む端末全て同一IPとして払い出されるため)

考慮点が多い上に労力との費用対効果も薄いので、

  1. どこかで妥協点を付ける
  2. アカウントと個人情報を紐付けDBに保管し、1人1票にこだわる

上記のいずれかの戦略を選ぶこととなります。
(といっても後者でも悪意ある人がでたらめな情報入れるから1人1票は無理そうですが)

後者の場合は、個人情報の送信・DB登録が伴うため、
より厳密なセキュリティ要件の担保が必要となりますけどね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/26 04:34

    核心をつかれ私の中での回答が見つかりました。ありがとうございました。

    キャンセル

+7

個人を特定しない以上、一人1回の投票をサーバ側で検出するのは不可能です。

IPアドレスでの制限をあげている方もいますが、むしろ善良な投稿者の投稿を制限することになるので、制限すべきではないと思います。
(会社やマンションインターネット、学校等でインターネットゲートウェイを共有している場合、同じIPアドレスで別人というケースは多々あります。また、携帯のIPアドレスも重複する可能性がかなり少ないですがあります)

方向性としては、「アカウント登録のハードルを如何に下げるか」を検討するのが正しいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/25 12:29

    どうでもいい話ですが、
    当方宅はマンションなんで、IPではじかれると他の部屋の人が投票したら投票できなくなります(

    そういう意味だとIPベースの判定はローカルネットワーク内でしか現実的ではなさそうですね。

    キャンセル

  • 2017/01/25 12:54

    ローカルなら個人を特定したほうが現実的かと。
    ヒモ付も簡単にできると思いますし。

    回答にも書きましたが、IPアドレスベースで投稿回数を1回に制限するのは、発想として間違いです。
    IPアドレスが個人と1対多、多対1で結ばれる以上、個人を特定する材料としては非常にあいまいなので、善良な使用者に影響を与える可能性を考えると採用は出来ないです。

    ローカルで扱うとしても、
    ・一人2台以上の環境がないこと
    ・共有端末がないこと
    ・DHCPのリフレッシュに巻き込まれないこと
    等、無駄な確認を多数しなければならなくなります。
    VPNとか言い出したらホントメンドイです。

    それよりも他のログイン情報をシングルサインオン的に使用して、個人を特定するほうが現実的です。

    キャンセル

  • 2017/01/25 16:46

    > te2jiさん
    なるほど、あまり詰めて考えてなかったので参考になります。

    ローカルだと認証サーバ立ててのSSOはよく聞きますが、
    インターネットとなるとSSO的に考えるとOAuthを利用して認証は委譲する方が有用になるんですかね。

    キャンセル

  • 2017/01/25 16:56

    最近、firebase を利用し始めたんですけど、作る側も登録する側もものすごく楽になりそうです。個人的に認証の外だしはそうとうありだと思います。

    キャンセル

+3

まぁよくあるのはEメールを送らせ、返信のEメールで投票コードのついた
urlを返信することです。
1Eメールアドレスあたり1回の制限は書けられます。
ただしそれでも捨IDを複数もっているユーザーは何度でも投票できます
ブラウザのセッションとからめてやれば少しは複数投票は防げますが
(同じブラウザからの連続投票を見極められる)
結局クッキーを消したりすればそれも効果がよわくなります

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/25 10:51

    これ、面白いですね。やったことありませんでした。

    キャンセル

  • 2017/01/25 12:22

    横槍ですが、
    その発想には至りませんでした。

    1人1回の完全な対策にはなりませんが、
    選択肢としては大いにありですね。

    キャンセル

  • 2017/01/25 15:23

    面白い発想ですが、「データベースには投票の結果のみを記録しクライアントの情報などその他の情報は、 データ量節約の為に保存しないようにしたいです」に反するかもしれませんね(既出のメールアドレスをデータベースに登録しなければならないので)。
    「データベースにユーザデータを保存しない」の要件が個人を特定不可能に至らしめているので、既にいわれているようにどこかで妥協点を作るしかなさそうです。

    キャンセル

+2

皆様回答ありがとうございます。
全ての回答を読みいろいろ考えたのですがやはり皆様の言われるようにデータベースに情報を蓄えないと制限は不可能だと分かりました。

今回はそれほど投票の結果に重要性がないので、ユーザーの負担とデータベースの容量の軽減を重視してまず実装はCookieで制限することにしました。
結果の重要性が高い場合は個人情報をデータベースに登録することにし、容量の節約については保存期限を定めて投票結果を破棄するなどまたその時に考えたいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    不動産登録サイト

    お世話になります。 ただいま練習としてphpを使いあるjsonファイルに入っている物件情報をphpにエンコードして管理画面のようなものを用意してそちらで物件の新規登録、追加、削除

  • 解決済

    phpの中でjavascriptを実行して変数に格納

    PHPの中でjavascriptを実行して、その結果をPHPの変数に格納するにはどのようにすれば良いでしょうか? 例えば、 <script> hoge = 1+2; </scr

  • 解決済

    【PHP】ファイルアップロードの重さ制限の動的変更法

     質問 PHPとJavaScriptを用いてファイルの非同期アップロード時の, PHPのアップロード制限を動的に緩くしたい. 例)デフォルト2MBを300MBに,など. 例

  • 受付中

    window.openで開いた画面にPOSTで値を渡す方法はありますか

    a.phpからwindow.openでb.phpを開きます。 a.phpで入力した情報をb.phpにPOSTで渡す方法はありますでしょうか? sub = window.op

  • 解決済

    操作ログの残し方

    前提・実現したいこと 現在,ユーザが行ったシステムの操作ログを残そうとしております. そこで,radioボタンで選択したログをはきだし,はきだしたログをユーザがボタンを押した(

  • 解決済

    javascript,php,MySQL間の変数のやり取りがうまく行きません...

    修正 パスワード等個人情報が含まれる接続部分以外は全部のせました。 また、回答してくださった方修正箇所を書き直しました。 最初初心者マークをつけることを忘れていましたがja

  • 解決済

    base64を使った画像取得の方法がうまくいきません。

    画像をbase64にエンコードしてデータベースに保存するまでは恐らくできたと思うのですがそれを呼び出す際の処理がよくわかりません。 base64は64種類の文字列に置き換えて

  • 受付中

    時間の足し算

    以前moriss.jsというグラフ描写ライブラリの使い方がよくわからず、質問させて頂きました。 今回は、値の管理についてです。質問は2つあります。 現在、勉強時間の管理サイ

同じタグがついた質問を見る

  • PHP

    20256questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    16326questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • SQL

    2377questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

  • Cookie

    176questions

    HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。