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

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

ただいまの
回答率

90.51%

  • PHP

    24024questions

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

  • JavaScript

    20387questions

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

jsゲームで得点をサーバーに送る時、偽造されないようにするには

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,086

webgoto

score 29

JavaScript(jQeury)を使用し、スロットのゲームを作りました。
イメージ説明
3箇所の数字をクリックして、その結果をサーバーにajaxで送信します。

プログラム

<span id="slot1" class="slot"></span>
<span id="slot2" class="slot"></span>
<span id="slot3" class="slot"></span>

<script>
$(function(){

    var stop = 0;

    //スロット動かす
    var slot1_timer = setInterval(function(){
        $('#slot1').text(Math.floor(Math.random()*10));
    }, 100);
    var slot2_timer = setInterval(function(){
        $('#slot2').text(Math.floor(Math.random()*10));
    }, 100);
    var slot3_timer = setInterval(function(){
        $('#slot3').text(Math.floor(Math.random()*10));
    }, 100);

    //スロット止める
    $('#slot1').one('click', function(){
        clearInterval(slot1_timer);
        if(++stop === 3){
            sendPoint();
        }
    });
    $('#slot2').one('click', function(){
        clearInterval(slot2_timer);
        if(++stop === 3){
            sendPoint();
        }
    });
    $('#slot3').one('click', function(){
        clearInterval(slot3_timer);
        if(++stop === 3){
            sendPoint();
        }
    });

    //得点送信
    var sendPoint = function(){
        $.post( 'http://example.net/point/',{
            point: $('.slot').text(),
            token: '<?php echo $_SESSION['token'] = sha1(uniqid(mt_rand(), true)); ?>' //CSRF対策
        });
    };

});
</script>

その際、ソースコードを読むと
http://example.net/point/に
POST送信でpointとtokenの値を送ればよい事がわかってしまい、
pointを好きな値でリクエストを送れば、得点の偽造が出来てしまいます。

得点を正確に取得する方法はありますでしょうか。
ポイントを受け取るサーバーサイドはPHPを使用します。

よろしくお願い致します。

追加質問

そもそも今回のプログラムはアルゴリズムの時点で実現不可であるとわかりました。
今回のゲームとは関係なく
インタラクティブにクライアント側からサーバー側にデータを送る時の
ロジックの参考になるような
サイトや書籍、検索キーワードなどはありますでしょうか?

よろしくお願い致します。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+3

JavaScriptの性質上、原理的に不可能です。

JavaScriptで実行するとなると、ブラウザ側で実行する=ブラウザにコードを送信している状態なので、どんな暗号化アルゴリズムを実行しようとも、アルゴリズムも鍵も入手可能となるため、意味がありません。

不正を完全に防ごうとすれば、PHPで得点や結果まで決めておいて、JavaScriptはそれを表示するだけ、という方法しかなさそうです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/09/08 17:54

    今回のやり方ではjsの仕様上、無理なのですね。
    根本から間違っていることがわかり、良かったです。
    利用している時は気づかなかったですが、他のサービスではサーバーで処理したデータをうまく使用しているのですね。
    ご回答ありがとうございました。

    キャンセル

checkベストアンサー

+2

この手の処理は結果をクライアントサイドで確定してはいけません。
ajaxで常にサーバーからデータをもらい、サーバー側でセッションでデータを持てば
クライアント側で操作することはできません。

追記

一応、簡単なサンプル書いときますね
slot.htm

<style>
span {
display:table-cell;
width:100px;
height:100px;
text-align:center;
vertical-align:middle;
font-size:80px;
border:1px solid #000000;
}
</style>
<script src="jquery.js"></script>
<script>
var data={};
var done={};
var timer_id={};
$(function(){
  $('.slot').each( function(){
    var id=$(this).prop('id');
    done[id]=false;
  });
  $('#start').click(function(){
    for(i in done){
      if(done[i]) return false;
    }
    clearData();
    $('.slot').each( function(){
      var id=$(this).prop('id');
      if(!done[id]){
        clearInterval(timer_id[id]);
        timer_id[id] = setInterval(function(){ $('#'+id).text(Math.floor(Math.random()*10));}, 100);
        done[id]=true;
      }
    });
  });
  $('.slot').click( function(e){
    var id=$(this).prop('id');
    if(typeof(data[id])=="undefined" && done[id]){
      setData(id);
    }
  });
});
function clearData(){
  $.ajax({ 
  url : "get.php",
  type:"post",
  dataType:"json",
  data :{"t":(+new Date())},
  });
  data={};
}
function setData(id){
  $.ajax({ 
  url : "get.php",
  type:"post",
  dataType:"json",
  data :{"v":id,"t":(+new Date())},
  success: function(msg){
    data[id]=msg[id];
    clearInterval(timer_id[id]);
    $("#"+id).html(msg[id]);
    done[id]=false;
  },
  });
}
</script>
<span id="slot1" class="slot">0</span>
<span id="slot2" class="slot">0</span>
<span id="slot3" class="slot">0</span>
<input type="button" id="start" value="start">

get.php

<?PHP
session_start();
$v=filter_input(INPUT_POST,"v",FILTER_VALIDATE_REGEXP,["options"=>["regexp"=>"/^slot[0-9]+$/","default"=>null]]);
if(is_null($v)){
  unset($_SESSION["data"]);
  print json_encode(null);
}else{
  $_SESSION["data"][$v]=mt_rand(0,9);
  print json_encode($_SESSION["data"]);
}
?>

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/09/08 18:05

    サーバー側で数値を決めた場合、
    利用者が数字が見えたタイミングで押しても、関係ない数字がでてしまうので、方法はないかなと思いまして。
    (この切り替え速度では見て押せる人はいないでしょうけど…)
    やはり根本が間違っていましたね。
    ご回答ありがとうございました。

    キャンセル

  • 2016/09/09 12:05

    サンプルのプログラムありがとうございます。
    いろいろ試してみたいと思います。

    キャンセル

0

コメントで

  サーバー側で数値を決めた場合、
利用者が数字が見えたタイミングで押しても、関係ない数字がでてしまう

とありますが、クリックしたタイミングでスロットが徐々に止まるようにアニメーションをゆっくりにしていき、そのタイムラグの間にサーバで決定した値を表示するというふうにするのはどうでしょうか?
演出でユーザーの体感を変えるというか…

あくまでも見えた数字をビシッと目押しするゲームなのであればダメですかね

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/09/09 12:04

    なるほど、見せ方の方法、参考になりました。
    実現できること、出来ないことを考えて仕組みを作らないといけないですね。
    ご回答ありがとうございました。

    キャンセル

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

  • PHP

    24024questions

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

  • JavaScript

    20387questions

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