Node系列学习之登录实现(一)

167 阅读1分钟

这是我参与更文挑战的第13天,活动详情查看:更文挑战

cookie

  • 存储在浏览器的一段字符串(最大5KB)

  • 跨域不共享

  • server端可以修改 cookie 并返回给浏览器

  • 浏览器中也可以通过js修改 cookie (有限制)

    在客户端 : document.cookie = '' // 累加cookie

server端操作cookie

查看cookie

  // 解析cookie
  req.cookie = {}
  const cookieStr = req.headers.cookie || ''
  cookieStr.split(';').forEach(item => {
    if(!item) {
      return
    }
    const arr = item.split('=')
    const key = arr[0]
    const val = arr[1]
    req.cookie[key] = val
  })
  console.log('req.cookie',req.cookie);

修改cookie

res.setHeader('Set-Cookie', `username=${data.username}; path=/`)

在登录接口中设置: 登录成功时,服务器设置cookie返回给浏览器

// 登录
  if (method == 'POST' && req.path == '/api/user/login') {
    const { username, password } = req.body
    const result = login(username,password)
    return result.then(data => {
      if(data.username) {
        res.setHeader('Set-Cookie', `username=${data.username}; path=/`)
        return new SuccessModel()
      }
      return new ErrorModel('登录失败~')
    })
  }

服务端设置不允许客户端更改cookie值

res.setHeader('Set-Cookie', `username=${data.username}; path=/; httponly`)

获取cookie过期时间

// 获取cookie过期时间
const getCookieExpires= () => {
  const d = new Date()
  d.setTime(d.getTime() + 24 * 60 * 60 * 1000)
  return d.toGMTString()
}
// 设置cookie
res.setHeader('Set-Cookie', `username=${data.username}; path=/; httponly; expires=${getCookieExpires()}`)

完整文件:

router/user.js

const { login } = require('../controller/user')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 获取cookie过期时间
const getCookieExpires= () => {
  const d = new Date()
  d.setTime(d.getTime() + 24 * 60 * 60 * 1000)
  return d.toGMTString()
}
const handleUserRouter = (req, res) => {
  const method = req.method

  // 登录
  if (method == 'POST' && req.path == '/api/user/login') {
    const { username, password } = req.body
    const result = login(username,password)
    return result.then(data => {
      if(data.username) {
        res.setHeader('Set-Cookie', `username=${data.username}; path=/; httponly; expires=${getCookieExpires()}`)
        return new SuccessModel()
      }
      return new ErrorModel('登录失败~')
    })
  }

  // 登录验证的测试
  if(method == 'GET' && req.path == '/api/user/login-test') {
    if(req.cookie.username) {
      console.log('req.cookie', req.cookie);
      return Promise.resolve(new SuccessModel())
    }
    return Promise.resolve(new ErrorModel('尚未登录~'))
  }
}
module.exports = handleUserRouter

app.js

const querystring = require('querystring')
const handleBlogRouter = require('./src/router/blog.js')
const handleUserRouter = require('./src/router/user.js')

// session数据

const SESSION_DATA = {}

// 用于处理 postData
const getPostData = req => {
  return new Promise((resolve, reject) => {
    if (req.method !== 'POST') {
      resolve({})
      return
    }
    // 非json数据类型,忽略并返回{}
    if (req.headers['content-type' !== 'application/json']) {
      resolve({})
      return
    }
    // 正确的
    let postData = ''
    req.on('data', chunk => {
      postData += chunk.toString()
    })
    req.on('end', () => {
      if (!postData) {
        resolve({})
        return
      }
      // 成功返回
      resolve(JSON.parse(postData))
    })
  })
}

const serverHandle = (req, res) => {
  res.setHeader('Content-Type', 'application/json')

  // 获取path
  const url = req.url
  req.path = url.split('?')[0]

  // 解析 query
  req.query = querystring.parse(url.split('?')[1])

  // 解析cookie
  req.cookie = {}
  const cookieStr = req.headers.cookie || ''
  cookieStr.split(';').forEach(item => {
    if (!item) {
      return
    }
    const arr = item.split('=')
    const key = arr[0].trim()
    const val = arr[1].trim()
    req.cookie[key] = val
  })

  // 解析session
  const userId = req.cookie.userId
  if (userId) {
    if (!SESSION_DATA[userId]) {
      SESSION_DATA[userId] = {}
    }
  } else {
    userId = `${Date.now()}_${Math.random()}`
    SESSION_DATA[userId] = {}
  }
  req.session = SESSION_DATA[userId]

  // 处理 postData
  getPostData(req).then(postData => {
    req.body = postData
    // 处理 blog 路由 旧

    // const blogData = handleBlogRouter(req, res)
    // if (blogData) {
    //   res.end(JSON.stringify(blogData))
    //   return
    // }

    // 处理 blog 路由 新
    const blogResult = handleBlogRouter(req, res)
    if (blogResult) {
      blogResult.then(blogData => {
        res.end(JSON.stringify(blogData))
      })
      return
    }

    // 处理 user 路由
    // const userData = handleUserRouter(req, res)
    // if (userData) {
    //   res.end(JSON.stringify(userData))
    //   return
    // }
    const userResult = handleUserRouter(req, res)
    if (userResult) {
      userResult.then(userData => {
        res.end(JSON.stringify(userData))
      })
      return
    }

    // 未命中路由, 返回404
    res.writeHead(404, { 'Content-Type': 'text/plain' })
    res.write('404 Not Found\n')
    res.end()
  })
}
module.exports = serverHandle

session

先说一下cookie可能会暴露的问题: 可能暴露用户敏感信息

解决: cookie中存储userId, server端对应username

session的学习还没有完成,暂时没啥可说的,等学完后再更新内容吧~

今天学习了cookie和session相关的后端知识, 对cookie与session有进一步的了解了,之前因为所接手的项目都是使用token来进行登录管理的,对cookie和session的了解不多, 通过今天的学习对cookie基本没啥问题了, 明天搞session~