您的位置:

前后端分离session问题

一、前后端分离session请求

在前后端分离的架构下,前端与后端不再共享session,因为后端应用是无状态的,每次请求都是新的请求,不保存上次请求的状态,所以前端每发送一次请求,都需要从新获取用户信息进行验证。


// 前端请求示例
fetch('/api/userInfo')
  .then(response => response.json())
  .then(data => console.log(data))

二、前后端分离为什么不能用session

前后端完全分离后,由于前端不再接受后端传来的渲染好的HTML页面,而是后端只提供RESTful API接口,前端通过AJAX请求后台返回的JSON数据自己进行渲染,所以后台不再需要用session来保存状态,前端使用session效果不好甚至有风险:

  • session实现复杂,需要后台程序开发共享session机制,前端需要保持session的一致性。
  • session空间大小有限制,过多的数据会占用大量的内存,并且session可以被其他应用篡改。

而采用令牌(token)作为身份标识,则前后端都不再需要保存状态。后台验证通过后,生成一个令牌,将其返回给前端。后端不再保存令牌信息,前端保存令牌并在随后的请求中携带令牌,并随请求传递给后端。后端收到请求后验证携带的令牌,验证通过后则认为是合法请求,并返回所需要的结果。


// 后端生成令牌返回示例
const jwt = require('jsonwebtoken')
const token = jwt.sign({
  username: 'jerry',
  exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24) // 过期时间1天
}, 'jwt_secret')
ctx.response.body = {
  code: 200,
  token: token
}

三、前后端分离session还有用吗

前后端分离后,不再需要session的作用了,采用令牌(token)的方式来代替session。使用令牌的优势在于前后端各自按照约定来生成、验证、传递、存储令牌,实现了无状态无session的前后端分离。

四、前后端分离session怎么传递

前后端分离架构中,使用令牌(token)代替session来保存用户登录状态,而令牌是通过Authorization请求头来传递的,格式为Bearer Token。


// 前端请求示例
fetch('/api/userInfo', {
  headers: {
    Authorization: 'Bearer ' + token
  }
})
  .then(response => response.json())
  .then(data => console.log(data))

五、vue前后端分离session

在Vue前后端分离架构中,同样采用令牌(token)的方式来代替session。在Vue应用中,可以将令牌存储在Vuex或者localstorage中,在每次请求API时携带对应的令牌来获取响应数据。


// Vue请求示例
methods: {
  fetchData() {
    const token = store.state.token
    axios.get('/api/userInfo', {
      headers: {
        Authorization: 'Bearer ' + token
      }
    })
      .then(response => {
        store.commit('setUserInfo', response.data)
      })
      .catch(error => {
        console.error(error)
      })
  }
}

六、前后端分离获取session

前后端分离架构中,不再采用session来保存用户状态信息,可以通过发送请求来获取用户信息。前端发送请求携带合法的令牌(token),后端验证令牌并返回相应的用户信息。


// 后端获取用户信息示例
const jwt = require('jsonwebtoken')
const token = ctx.header.authorization.split(' ')[1] // 获取令牌
try {
  const decoded = jwt.verify(token, 'jwt_secret') // 验证令牌
  const user = await User.findById(decoded.username)
  ctx.response.body = {
    code: 200,
    user: user
  }
} catch(error) {
  ctx.response.status = 401
  ctx.response.body = {
    code: 401,
    message: '无效的令牌'
  }
}

七、前后端session不一致

在前后端分离的架构下,前端与后端不再共享session,不会出现session不一致的问题。

八、前后端分离 session每次都是新的

在前后端分离架构下,后端采用了无状态设计,每次请求都不存储上一次请求的会话状态信息,每次请求都是一次全新的请求,不存在session信息。

完整代码示例


// 前端请求
fetch('/api/userInfo', {
  headers: {
    Authorization: 'Bearer ' + token
  }
})
  .then(response => response.json())
  .then(data => console.log(data))

// 后端令牌生成
const jwt = require('jsonwebtoken')
const token = jwt.sign({
  username: 'jerry',
  exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24) // 过期时间1天
}, 'jwt_secret')
ctx.response.body = {
  code: 200,
  token: token
}

// 后端获取用户信息
const jwt = require('jsonwebtoken')
const token = ctx.header.authorization.split(' ')[1] // 获取令牌
try {
  const decoded = jwt.verify(token, 'jwt_secret') // 验证令牌
  const user = await User.findById(decoded.username)
  ctx.response.body = {
    code: 200,
    user: user
  }
} catch(error) {
  ctx.response.status = 401
  ctx.response.body = {
    code: 401,
    message: '无效的令牌'
  }
}