代码之家  ›  专栏  ›  技术社区  ›  Ahmad Mobaraki

是否可以在vue路由器中锁定除一条之外的所有路由?它安全吗?或者我应该用另一种方法?

  •  5
  • Ahmad Mobaraki  · 技术社区  · 9 年前

    在Laravel5.4和VueJs中,用户回答的每个问题都有一个Ajax请求。我想要的是防止用户看到其他页面。每一页的可视时间不得超过120秒。用户应该无法单击“后退”按钮并查看以前的页面。这有可能吗?

    我想用创建此应用 Vuejs vue-router ,我做了一些研究,但结果不多!

    或者我不应该使用 ,并使用我自己的简单路由器,例如:

    $("#page1").show();
    $("#page2").hide();
    $("#page3").hide();
    .
    .
    // after 120 secs 
    $("#page1").hide();
    $("#page2").show();
    $("#page3").hide();
    .
    .
     // i think this is not secure !
    

    如有任何想法,我们将不胜感激。非常感谢。

    在这个测试中,用户可以看到 English words 从中随机选择 words results fake_words 随机选择50个单词的表格 actual words 如果用户点击假词超过3次,测试将失败。最终结果将告诉用户他有多少词汇技能。

    更新2: 我试着用 ,但在开始编写代码之前,我认为可能不应该用 因为所有问题都是在一个查询中随机从数据库中获取的,所以在考试开始之前,所有问题都会发送(ajax)到浏览器,现在我该怎么办?将它们分割成不同的数组,并将每个问题数组发送到我的一个页面?我必须这样做吗?我不能只用一个吗 v-for 为了他们?如果我决定改变问题的数量怎么办?然后我想我必须每次触摸我的代码,并为其创建新页面 vue路由器

    3 回复  |  直到 9 年前
        1
  •  3
  •   online Thomas    9 年前

    如果这真的是像考试这样的高风险代码,你应该重新考虑你的方法:“ Never trust the client “。我建议为后端编写代码来解决您的问题。

    1) 使用中间件保护端点,即:

    2) 在访问页面时创建时间戳

    注意:我希望他们也必须在线回答,否则就不安全了:如果问题放在浏览器窗口中,他们可以始终缓存这个问题,即使有最好的代码,他们也可以在屏幕上拍照。

    编辑: pagination

    编辑2: 当devtools打开时,我还会向服务器发送通知。你可以试试 https://github.com/sindresorhus/devtools-detect

        2
  •  2
  •   Bas    9 年前

    const app = new Vue({
        el: '#app',
        data: {
            stepOne: 1,
        }
    });
    
    <step v-if="step==1"></step>
    
    timeInterval = setInterval(function() {
        goToNextStep(2);
        this.$parent.stepOne = 0;
    }.bind(this), 12000);
    
        3
  •  1
  •   Lucky Soni    9 年前

    <template>
      <div>
        <div id="question" v-if="question">
          {{question}}
          <button @click="nextQuestion();" v-if="hasNextQuestion()"></button>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        data() {
          return {
            curQuestionNo: 0,
            maxQuestions: 4
            question: null,
            timer: null
          }
        },
        methods: {      
          fetchQuestion () {
            // return one question at a time from the server. Storing all questions on the client is not recommended.
            var url = 'https://myapi.com/question?curQuestionNo=' + this.curQuestionNo;
    
            axios.get(url) // or however you prefer to make ajax calls
              .then(res => {
                this.question = res.question;
                this.curQuestionNo++;
                this.stopTimer();
                if(this.hasNextQuestion()) {
                  this.startTimer();
                }
              })
              .catch(() => {
                // do some error handling
              });
          },
          startTimer () {
            this.timer = setTimeout(() => {
              this.nextQuestion();
            }, 120 * 1000);
          },
          stopTimer () {
            clearTimeout(this.timer);
          },
          nextQuestion () {
            if(this.curQuestionNo > 0) {
              this.markAnswered(function() {  
                this.fetchQuestion();
              })
            } else {
              this.fetchQuestion();
            }
          },
          markAnswered (cb) {
            // record the answered question on server
            // server should only send the next question after this
            var url = 'https://myapi.com/mark-complete?curQuestionNo=' + this.curQuestionNo;
    
            axios.post(url) 
              .then(res => {
                this.fetchQuestion();
              })
              .catch(() => {
                // do some error handling
              });
          },
          hasNextQuestion () {
            return this.maxQuestions - (this.curQuestionNo + 1) > 0;
          }
        },
        created () {
          this.nextQuestion();      
    
        }
      }
    </script>
    

    在服务器端,我建议采用以下方法:

    1. 在API将下一个问题返回给客户端之前,请确保用户已回答了上一个问题,或者允许回答该问题的时间范围已过期。这可以很简单地实现,只需在数据存储中保留一个计数器,以记录每个用户上次回答(或过期)的问题编号。不应允许用户回答等于或小于记录中数字的问题。服务器只应发送比记录中的数字大一的问题编号。

    Route::get('question', function(){
        $curQuestionNo = intVal(Input::get('curQuestionNo'));
        $user = User::find($userId); // get the logged in user, for example
        if($user->current_question_number === $curQuestionNo) {
          $question = Question::where('question_no', $curQuestionNo + 1);
          $question->sent_at = time(); // store the time when the question was sent
          return $question
        } else {
          // deny access
        }
    });
    
    Route::post('mark-complete', function(){
        $curQuestionNo = intVal(Input::get('curQuestionNo'));
        $user = User::find($userId); // get the logged in user, for example
        $question = Question::find($curQuestionNo);
        if($question->sent_at > 120 seconds) {
         // do not record answers
        } else {
          // record answers
        }
        $user->current_question_number = $curQuestionNo;
        $user->save();
    });