session cookie 在参加考试时过期后如何自动注销用户?

How do you auto logout user after session cookie expires while taking a test?

我正在构建一个 MVC ExpressJS 测试应用程序,并试图在用户停止回答测试问题后自动注销。我不断收到“错误 [ERR_HTTP_HEADERS_SENT]:将它们发送到客户端后无法设置 headers”。我有一个在应用程序中可用的注销按钮功能,但自动化似乎不起作用。

这是在问题控制器中不起作用的块代码:

  setInterval(function() {
    if (req.session.cookie.maxAge <= 0) {
      clearInterval(this);
      req.session.destroy(err => {
        console.log("Time's up, logging out user!");
        if (err) throw err;

        res.clearCookie(config.sessionData.SESS_NAME);
        console.log("redirecting..");
        return res.render('login_user');
      })  
    } else {
      console.log("Time left: ", req.session.cookie.maxAge / 1000, "seconds left");
    }
  }, 10000);

这是整个控制器的代码:

const pool = require('../models/db');
const config = require('../config');

module.exports = (req, res) => {
  let time_start;
  let qTotal;
  let mcLimit;
  let question_id = req.session.question_id;
  let quiz_id = req.session.quiz_id;

  setInterval(function() {
    if (req.session.cookie.maxAge <= 0) {
      clearInterval(this);
      req.session.destroy(err => {
        console.log("Time's up, logging out user!");
        if (err) throw err;

        //res.clearCookie(config.sessionData.SESS_NAME);
        console.log("redirecting..");
        return res.render('login_user');
      })  
    } else {
      console.log("Time left: ", req.session.cookie.maxAge / 1000, "seconds left");
    }
  }, 10000);
  
  console.log("Question_id: " + question_id);
  console.log("Quiz_id: " + quiz_id);
  pool.query(
      `SELECT Quiz_id, Question_id, Prompt From Govt_questions WHERE Question_id = ?;
      SELECT Answer_prompt From Govt_answers Where Question_id = ?;
      SELECT * FROM Govt_answers WHERE Question_id = ?;
      SELECT Answer_id FROM Govt_answers WHERE Question_id = ?;
      SELECT Question_id From Govt_questions`
      ,[question_id, question_id, question_id, question_id]
      )
    .then(rows => {
      if (question_id > qTotal) {
        res.redirect('progress-report');
      } else {
        //temp is correct answers
        var temp = [];
        var count = rows[1].length;
        var govtQuestions = rows[0][0];
        var govtAnswersId = rows[3];
        var govtAnswers = rows[2];
        quiz_id = govtQuestions['Quiz_id'];
        qTotal = rows[4].length;
        req.session.time_start = new Date().toISOString().slice(0, 19).replace('T', ' ');
        console.log("JSON?: " + JSON.stringify(govtAnswers));

        for (var i = 0; i < count; i++) {
          temp.push(rows[2][i].Correct.toJSON().data[0]);//this loops through all answers and pushes binary data as true and false answers
        }
        mcLimit = temp.reduce((total, val) => {
          return total + val;
        });

        return res.render('show_questions', {
          quizId: govtQuestions['Quiz_id'],
          questionNum: govtQuestions['Question_id'],
          question: govtQuestions['Prompt'],
          answerId: govtAnswersId,
          answers: govtAnswers,
          mcLimit: mcLimit,
          questionTotal: qTotal,
          userName: req.session.user_name
        });
      }
    })
    .catch(err => {
      console.log(err);
    })
};

我通过注销用户客户端解决了我的问题,因为在用户参加测试时我有一个可用的注销按钮。 我确定我的 cookie 已设置:

//30 min time
global.timer = 1000 * 60 * 30;
app.use(session({
    name: config.sessionData.SESS_NAME,
    secret: config.sessionData.SESS_SECRET,
    cookie: {
        maxAge: timer
    },
    resave: false,
    saveUninitialized: false
}));

然后在 html/pug 页面上我添加了这个脚本,它接受 cookie 变量并启动一个计时器,当计时器结束时,用户将自动注销。

        let time = #{timer};
        let half = (time/2);

        window.setTimeout(() => {
            alert("logging you out soon, unless you pick an answer!");
        }, half)
        
        window.setTimeout(() => {
            document.getElementById("log-out").click();
        }, time)

我希望这可以帮助其他一直试图自己解决这个问题的人。