Express 当cookie在Nuxt中过期时,如何自动注销用户?

Express 当cookie在Nuxt中过期时,如何自动注销用户?,express,vue.js,cookies,nuxt.js,Express,Vue.js,Cookies,Nuxt.js,我正在使用执行登录使用快速会话,它的工作非常完美 app.js文件 const express = require('express') const session = require('express-session') const app = express() app.use(express.json()) app.use(express.urlencoded({ extended: true })) // session middleware app.use( session({

我正在使用执行登录使用快速会话,它的工作非常完美

app.js文件

const express = require('express')
const session = require('express-session')
const app = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// session middleware
app.use(
  session({
    secret: 'super-secret-key',
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 60000 }
  })
)

// Create express router
const router = express.Router()

// Transform req & res to have the same API as express
// So we can use res.status() & res.json()
router.use((req, res, next) => {
  Object.setPrototypeOf(req, app.request)
  Object.setPrototypeOf(res, app.response)
  req.res = res
  res.req = req
  next()
})

// Add POST - /api/login
router.post('/login', (req, res) => {
  if (req.body.username === 'demo' && req.body.password === 'demo') {
    req.session.authUser = { username: 'demo' }
    return res.json({ username: 'demo' })
  }
  res.status(401).json({ message: 'Bad credentials' })
})

// Add POST - /api/logout
router.post('/logout', (req, res) => {
  delete req.session.authUser
  res.json({ ok: true })
})

app.use('/api', router)

module.exports = app
问题是当cookie过期时,用户仍在前端登录。如果他们访问一个端点,他们会被注销,因为我猜会调用nuxtServerInit,这会让用户不安

store/index.js

import axios from 'axios'

export const state = () => ({
  authUser: null
})

export const mutations = {
  SET_USER(state, user) {
    state.authUser = user
  }
}

export const actions = {
  // nuxtServerInit is called by Nuxt.js before server-rendering every page
  nuxtServerInit({ commit }, { req }) {
    if (req.session && req.session.authUser) {
      commit('SET_USER', req.session.authUser)
    }
  },
  async login({ commit }, { username, password }) {
    try {
      const { data } = await axios.post('/api/login', { username, password })
      commit('SET_USER', data)
    } catch (error) {
      if (error.response && error.response.status === 401) {
        throw new Error('Bad credentials')
      }
      throw error
    }
  },

  async logout({ commit }) {
    await axios.post('/api/logout')
    commit('SET_USER', null)
  }
}

如果没有websocket等待注销通知,您将无法在到期时立即注销用户。这就是为什么它会一直等到你再次尝试导航。如果您想立即注销用户,您可以创建一个Websocket,在cookie过期时等待来自服务器的信号

然而,这是一个特定的用例。大多数网站只是等待用户尝试另一个需要检查其令牌是否过期的操作,然后采取适当的措施


可以通过跟踪商店前端剩余的过期时间来简化此操作。然后,您可以使用
computed
属性检查用户剩余时间的不断递减倒计时。当这个值为零时,您可以运行您的突变。

非常接近这里的答案。其思想是在用户发布到登录路由时设置req.session.expires。目前的问题是在异步登录方法中,如何访问req.session

这是server/index.js文件

// Add POST - /api/login
router.post('/login', (req, res) => {
  if (req.body.username === 'demo' && req.body.password === 'demo') {
    req.session.authUser = { username: 'demo' }
    req.session.expires = req.session.cookie.expires.getTime()
    return res.json({ username: 'demo' })
  }
  res.status(401).json({ message: 'Bad credentials' })
})
export const actions = {
  // nuxtServerInit is called by Nuxt.js before server-rendering every page
  nuxtServerInit({ commit }, { req }) {
    if (req.session && req.session.authUser) {
      commit('SET_USER', req.session.authUser)
    }
    if (req.session && req.session.expires) {
      commit('SET_EXPIRES', req.session.expires)
    }
  },
  // How do you get req.session.expires HERE???
  async login({ commit }, { username, password }) {
    try {
      const response = await this.$axios.post('/api/login', {
        username,
        password
      })
      console.log(response, response.request, response.request.session)
      commit('SET_USER', response.data)
    } catch (error) {
      if (error.response && error.response.status === 401) {
        throw new Error('Bad credentials')
      }
      throw error
    }
  },

  async logout({ commit }) {
    await this.$axios.post('/api/logout')
    commit('SET_USER', null)
    commit('SET_EXPIRES', null)
  }
}
这是store/index.js文件

// Add POST - /api/login
router.post('/login', (req, res) => {
  if (req.body.username === 'demo' && req.body.password === 'demo') {
    req.session.authUser = { username: 'demo' }
    req.session.expires = req.session.cookie.expires.getTime()
    return res.json({ username: 'demo' })
  }
  res.status(401).json({ message: 'Bad credentials' })
})
export const actions = {
  // nuxtServerInit is called by Nuxt.js before server-rendering every page
  nuxtServerInit({ commit }, { req }) {
    if (req.session && req.session.authUser) {
      commit('SET_USER', req.session.authUser)
    }
    if (req.session && req.session.expires) {
      commit('SET_EXPIRES', req.session.expires)
    }
  },
  // How do you get req.session.expires HERE???
  async login({ commit }, { username, password }) {
    try {
      const response = await this.$axios.post('/api/login', {
        username,
        password
      })
      console.log(response, response.request, response.request.session)
      commit('SET_USER', response.data)
    } catch (error) {
      if (error.response && error.response.status === 401) {
        throw new Error('Bad credentials')
      }
      throw error
    }
  },

  async logout({ commit }) {
    await this.$axios.post('/api/logout')
    commit('SET_USER', null)
    commit('SET_EXPIRES', null)
  }
}

您可以注册一个服务工作者来异步侦听cookie存储中的更改(这也不需要连续轮询!)这是相当新的,并且可能不支持某些浏览器。这是一篇关于它的文章

或者,您可以使用通知前端到期并调用注销方法。您的服务器应该能够跟踪到期并发送推送

如果他们访问端点,他们会注销,因为我是 猜测会调用nuxtServerInit,这会使用户不安


老实说,这几乎是大多数网站的默认行为。除非您在构建Web应用时首先考虑安全性。

但是您将如何访问vuex store computed Property中的req.cookies创建cookie时,将某些内容(例如剩余时间)传递到前端,以便放置在
localStorage
中或直接放置在store中。感谢您的建议,我已经非常接近做到这一点,我遵循了在客户端上设置过期时间的方法。现在唯一的问题是,当我在vuex store操作中执行axios.post时,我无法访问req.session.expires,这是我在服务器登录路由中设置的,当用户向它发布时,axios响应不包含服务器的req.session,如果您有一些想法,甚至在下面发布了部分答案,这将非常有用