node.js原生開發服務端項目之使用本地node.js變量存儲session信息實現登錄

使用session實現登錄的思路:

1.服務端收到客戶端請求,解析請求頭獲取sessionId。

2.如果sessionId不存在,則生成一個唯一的sessionId,生成sessionId的規則可以根據自己需要設置,這裏使用時間戳+隨機數生成sessionId。並且設置cookie。

3.根據sessionId從SESSION_DATA這個全局變量中讀取session數據,如果不存在,初始化爲空對象{},如果存在,說明用戶已登錄過

4.用戶訪問localhost:8002/login?username=test&password=123登錄成功,存儲session數據到SESSION_DATA中。

5.可以通過訪問localhost:8002/getUserInfo獲取session中的登錄信息

const http = require('http')
const querystring = require('querystring')

const getCookieExpires = () => {
  const d = new Date()
  d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
  return d.toGMTString()
}

// 直接這麼設置session數據,session會存在nodejs進程中,會存在以下問題:
// 1.進程內存有限,如果訪問量過大,session過大,導致內存暴增。
// 2.線上環境,是多進程的,進程之間無法共享內存
const SESSION_DATA = {}

const server = http.createServer(async (req, res) => {

  // 設置返回格式爲JSON
  // 在原生的node開發中,res.end返回的永遠都是字符串,但是可以通過res.setHeader('Content-type', 'application/json')
  // 設置返回的數據格式,客戶端拿到返回結果會根據返回的數據格式解析數據
  res.setHeader('Content-type', 'application/json')

  const url = req.url
  req.path = url.split('?')[0]
  req.query = querystring.parse(url.split('?')[1])

  req.cookie = {}
  const cookie = req.headers.cookie || ''
  cookie && cookie.split(';').forEach(item => {
    const arr = item.split('=')
    const key = arr[0].trim()
    req.cookie[key] = arr[1].trim()
  })

  //解析session
  let sessionId = req.cookie.sessionId

  if(!sessionId){
    sessionId = `${Date.now()}_${Math.random()}`
    // httpOnly:只允許後端修改,不允許前端修改
    res.setHeader('Set-Cookie', `sessionId=${sessionId};path=/;httpOnly;expires=${getCookieExpires()}`)
  }
  req.session = SESSION_DATA[sessionId] = SESSION_DATA[sessionId] || {}


  if(req.method === 'GET' && req.path === '/login'){
    const { username, password } = req.query
    if(username === 'test' && password === '123'){
      req.session.username = 'test'
      req.session.password = '123'
      res.end('login success')
    } else {
      res.end('login fail')
    }
    return
  }

  if(req.method === 'GET' && req.path === '/getUserInfo'){
    if(req.session.username){
      res.end(JSON.stringify({ username: req.session.username, password: req.session.password }))
    } else {
      res.end('not login')
    }
    return
  }

  res.writeHead(404, { "Content-type": "text/plain" })
  res.write("404 Not Found\n")
  res.end()
})


server.listen(8002)

6.總結,使用node.js本地變量存儲session,有很大的問題,服務重啓,這些信息都會丟失,而且進程之間無法共享用戶信息,因此可以考慮將session數據存儲到redis中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章