5 votes

Est-il possible de verrouiller toutes les routes sauf une, dans vue-router ? Est-ce sûr ? Ou peut-être devrais-je utiliser une autre méthode ?

Je veux créer un examen en ligne, cet examen a 5 pages, il y a un compte à rebours (120 secondes) et 4 questions sur chaque page. Après 120 secondes, les utilisateurs sont automatiquement transférés à la page suivante, ou ils peuvent cliquer sur le bouton suivant avant cela.

Laravel5.4 et VueJs, il y a une requête Ajax pour chaque question à laquelle l'utilisateur répond. Ce que je veux, c'est empêcher l'utilisateur de voir d'autres pages. Chaque page doit être visible pendant 120 secondes maximum. L'utilisateur ne doit pas pouvoir cliquer sur le bouton retour et voir les pages précédentes. Est-ce possible ?

Je veux créer cette application avec Vuejs y vue-router mais je ne sais pas comment le mettre en œuvre avec vue-router J'ai fait quelques recherches mais je n'ai pas obtenu beaucoup de résultats !

Ou peut-être ne devrais-je pas utiliser vue-router et d'utiliser mon propre routeur simple, par exemple :

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

Nous vous remercions de nous faire part de vos commentaires. Je vous remercie de votre attention.

UPDATE : Dans cet examen, l'utilisateur peut voir une liste de English words choisis au hasard parmi les words table et rien d'autre ! L'utilisateur clique sur chaque mot dont il pense connaître la signification ! Et une requête ajax pour chaque clic afin de sauvegarder l'identifiant du mot en results table. Il existe également un fake_words un tableau de 50 mots est sélectionné de manière aléatoire en plus de la liste des mots. actual words si l'utilisateur clique sur les faux mots plus de 3 fois, le test échoue. Le résultat final indiquera à l'utilisateur son niveau de vocabulaire.

MISE À JOUR 2 : J'ai essayé de le faire avec vue-router mais avant de commencer à coder, j'ai pensé qu'il ne fallait peut-être pas l'implémenter avec vue-router Les questions sont extraites aléatoirement de la base de données en une seule requête, puis avant le début de l'examen, elles sont toutes envoyées (ajax) au navigateur, que dois-je faire ? Les découper en tableaux séparés et envoyer chaque tableau de questions à l'une de mes pages ? dois-je faire cela ? ne puis-je pas utiliser un seul tableau ? v-for Que se passe-t-il si je décide de changer le nombre de questions ? Dans ce cas, je pense que je dois modifier mon code à chaque fois et créer une nouvelle page pour vue-router ou supprimer une des pages.

3voto

Thomas Points 1652

S'il s'agit d'un code à haut risque comme un examen, vous devriez reconsidérer votre approche : " Ne jamais faire confiance au client ". Je vous suggère d'écrire du code pour le backend afin de résoudre votre problème.

1) Protéger le point d'accès à l'aide d'un logiciel intermédiaire (middleware) :

2) crée un horodatage de la visite de la page

3) N'accepte pas de nouveau message (réponse) de l'utilisateur après 120 secondes.

Note : J'espère qu'ils doivent aussi répondre en ligne, sinon cela ne peut pas être sécurisé : si la question est placée dans la fenêtre du navigateur, ils peuvent toujours mettre cette question en cache, même avec le meilleur code, ils peuvent prendre une photo de l'écran.

éditer : J'utiliserais pagination d'envoyer les questions une par une avec un temps limité.

modifier 2 : J'enverrais également une notification au serveur lorsque les outils de développement sont ouverts. Vous pouvez essayer https://github.com/sindresorhus/devtools-detect

2voto

Bas Points 1173

Peut-être que ces extraits vous aideront :

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);

1voto

Lucky Soni Points 2579

En ce qui concerne la sécurité, le choix du cadre JS n'aura que peu d'impact, voire aucun. Vue.js est un excellent choix. Voici un exemple de code qui vous aidera à démarrer :

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

En ce qui concerne le serveur, je recommande l'approche suivante :

  1. Envoyer une question par demande au client
  2. Assurez-vous que l'utilisateur a répondu à la question précédente ou que le délai imparti pour répondre à la question a expiré avant que l'API ne renvoie la question suivante au client. Pour ce faire, il suffit de conserver un compteur dans votre magasin de données afin d'enregistrer le numéro de la dernière question à laquelle l'utilisateur a répondu (ou qui a expiré). L'utilisateur ne doit pas être autorisé à répondre à une question dont le numéro est égal ou inférieur au numéro enregistré. Le serveur ne doit envoyer que le numéro de la question qui est supérieur d'une unité au numéro figurant dans l'enregistrement.

Exemple de code (je ne suis pas sûr de la syntaxe de Laravel 5 mais vous devriez vous en faire une idée) :

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();
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X