cookie在前后端项目中的简单实践

写在前面

这里是小飞侠Pan🥳,立志成为一名优秀的前端程序媛!!!

本篇文章同时收录于我的github前端笔记仓库中,持续更新中,欢迎star~

👉https://github.com/mengqiuleo/myNote


cookie在前后端项目中的简单实践

自己在学习cookie时,只是知道理论知识,理解还停留于“纸上谈兵”的阶段。

所以在这里开了一个小demo,来实践在项目中使用cookie。

这个demo:后端使用原生nodejs,前端并没有使用页面,前端发送请求使用postman

整个项目的源码收录于我的仓库中:https://github.com/mengqiuleo/myNote


项目搭建

项目目录:

├─ package-lock.json
├─ package.json
└─ src
   ├─ app.js
   ├─ main.js
   └─ routes
      └─ user.js

package.json

首先,

npm init -y

初始化项目。

然后,下载npm包:npm install nodemon --save

在package.json文件中加入一行调试:"dev": "nodemon src/main.js" 来启动项目


main.js

创建根目录src,然后在根目录下创建main.js,这是整个项目的入口。在 main.js 文件中,搭建一个服务器,代码如下:

const http = require('http')
const serverHandler = require('./app')

const server = http.createServer(serverHandler)

server.listen(3000)

解释上述代码:

如果不会使用原生nodejs搭建http服务器,请移步至此👉:【Nodejs】学习之常用内置模块

用原生nodejs代码搭建一个服务器,所有关于response 的返回语句,封装在 app.js 中。

所以在根目录下创建一个app.js


app.js

首先,搭建最基础的判断语句:

const querystring = require('querystring')

const serverHandler = (req,res) => {
  res.setHeader('Content-Type', 'application/json') //设置返回数据的格式
  const url = req.url // /api/user/login?username=zs&password=123

  req.path = url.split('?')[0] // /api/user/login
  req.query =  querystring.parse(url.split('?')[1]) // { username: 'zs', password: '123' }

  console.log("cookie: ",req.headers.cookie)

  // 改变cookie的格式:key-value(即对象形式)
  req.cookie = {}
  const cookieStr = req.headers.cookie || ''
  cookieStr.split(';').forEach(item => {
    if(!item){
      return
    }
    const arr = item.split('=')
    const key = arr[0].trim()//trim用来去除空格
    const val = arr[1].trim()
    req.cookie[key] = val 
  });

  //在这里对请求的不同路由(即不同页面)进行处理,然后拿到处理结果 userResult
  // ...

  res.end(userResult)//将处理结果返回
}

module.exports = serverHandler

解释:

  • 首先引入内置模块:querystring,用来分离参数。

    比如:/api/user/login?username=zs&password=123,这样的url传递过来的参数是一个字符串,那么我们就可以使用这个内置模块将参数转换成对象

    { username: 'zs', password: '123' }

  • 先用 req.url 拿到请求路径的参数

  • 然后我们给res添加两个属性:path 和 query。

    • path 用来存放路径,比如/api/user/login
    • query 用来存放参数,比如{ username: 'zs', password: '123' }。并且我们在这个使用querystring内置模块将参数转换成对象形式
  • 前端传过来的cookie是存放在req.headers.cookie

  • 因为cookie的格式并不方便处理,我们这里对cookie的格式进行处理(cookie的格式,我们可以在控制台中打印:document.cookie

    可以看到cookie的格式如下:

    ttcid=634f732d8a2046cabe641599776836ee30; _tea_utm_cache_2608={%22utm_source%22:%22infinitynewtab.com%22}; MONITOR_WEB_ID=5a6a0411-a419-4333-815f-116842e0c588; 
    

    可以看到,每个cookie之间用 ; 分开,然后每个cookie的格式都是:key=value

  • 我们这里把cookie转换成对象(key-value)的形式:

    req.cookie = {}
    const cookieStr = req.headers.cookie || '' //拿到所有的cookie
    cookieStr.split(';').forEach(item => { // 使用 ; 将每个cookie分开
      if(!item){
      	return
      }
      const arr = item.split('=')
      const key = arr[0].trim()//trim用来去除空格
      const val = arr[1].trim()
      req.cookie[key] = val 
    });
    
  • 接下来是对不同页面的处理,我们将处理路由的这部分代码单独放在一个文件routes/user.js

  • 然后在这个文件中引入routes/user.js

  • 那么这个文件(app.js)的整体代码如下

    const querystring = require('querystring')
    const handleUserRouter = require('./routes/user')
    
    const serverHandler = (req,res) => {
      res.setHeader('Content-Type', 'application/json') //设置返回数据的格式
      const url = req.url // api/user/login?username=zs&password=123
    
      req.path = url.split('?')[0] // /user/login
      req.query =  querystring.parse(url.split('?')[1]) // { username: 'zs', password: '123' }
    
      console.log("cookie: ",req.headers.cookie)
    
      req.cookie = {}
      const cookieStr = req.headers.cookie || ''
      cookieStr.split(';').forEach(item => {
        if(!item){
          return
        }
        const arr = item.split('=')
        const key = arr[0].trim()//trim用来去除空格
        const val = arr[1].trim()
        req.cookie[key] = val 
      });
    
      const userResult = handleUserRouter(req,res)//引入处理路由的 routes/user.js 文件
    
      res.end(userResult)
    }
    
    module.exports = serverHandler
    

routes/user.js

这个文件用来根据不同的请求路由,返回不同的结果

const handleUserRouter = function(req,res) {
  const method = req.method
  if(method === 'GET' && req.path === '/api/user/login'){
    const { username, password } = req.query
    const loginResult = loginTest(username,password) // loginTest是一个自己封装的函数,用来判断登录用户名和密码是否正确
    if(loginResult){
      res.setHeader('Set-Cookie', `username=${username}; path=/; expires=${setCookieExpireTime()}`)
      return {
        errorCode: 0,
        data: 'cookie设置成功'
      }
    }
    return {
      errorCode: -1,
      msg: '用户名或密码错误'
    }
  } else {
    if(req.cookie.username){
      return {
        errorCode: 0,
        msg: '已查询到cookie'
      }
    }
    return {
      errorCode: -1,
      msg: '请登录'
    }
  }
}

module.exports = handleUserRouter

解释:

  • 首先我们要拿到请求的方法:req.method

  • 我们要分不同的路由进行判断:

    • 如果请求的是登录页:/api/user/login 那么我们需要先取出来拼接在路径后面的参数:

      /api/user/login?username=zs&password=123

      const { username, password } = req.query
      const loginResult = loginTest(username,password) // loginTest是一个自己封装的函数,用来判断登录用户名和密码是否正确
      

      拿到用户名和密码后,使用loginTest函数进行校验,拿到校验的结果

    • 身份校验函数的封装:

      这里我们只是简单模拟,所以不会引入数据库,在这里将登录名和密码写成固定的

      // 判断用户名密码是否正确的函数
      const loginTest = function(username,password){
        if(username === 'zs' && password === '123'){//注意:因为参数的传递是字符串形式,所以即使密码是数字,也要用字符串的形式判断
          return true
        }
        return false
      }
      
    • 然后根据校验结果分情况讨论:

      if(method === 'GET' && req.path === '/api/user/login'){
        // ...
        //进行用户名和密码的校验,拿到校验结果:loginResult
        
        if(loginResult){ // 如果校验成功:那么就设置cookie,并且返回状态码为0,表示成功
          res.setHeader('Set-Cookie', `username=${username}; path=/; expires=${setCookieExpireTime()}`)
          return {
            errorCode: 0,
            data: 'cookie设置成功'
          }
        }
      
        //否则校验失败,返回状态码-1
        return {
            errorCode: -1,
            msg: '用户名或密码错误'
          }
        }
      
      }
      
  • 上面的代码中,我们在设置cookie时,可以对cookie设置过期时间:

    我们自定义封装一个过期时间的函数:

    //设置cookie过期时间的函数
    const setCookieExpireTime = function() {
      const date = new Date()
      date.setTime(date.getTime() + 10*1000)
      return date.toGMTString()
    }
    
  • 如果我们请求的是别的页面,那就需要判断是否存在cookie,如果有cookie,就允许放行,否则返回错误的状态码

    else { // else是对别的页面的请求
        if(req.cookie.username){ //如果存在这个cookie,允许放行
          return {
            errorCode: 0,
            msg: '已查询到cookie'
          }
        }
        return { //不存在这个cookie,那么就要先登录,设置cookie
          errorCode: -1,
          msg: '请登录'
        }
     }
    

routes/user.js 完整代码如下:

// 判断用户名密码是否正确的函数
const loginTest = function(username,password){
  if(username === 'zs' && password === '123'){//注意:因为参数的传递是字符串形式,所以即使密码是数字,也要用字符串的形式判断
    return true
  }
  return false
}

//设置cookie过期时间的函数
const setCookieExpireTime = function() {
  const date = new Date()
  date.setTime(date.getTime() + 10*1000)
  return date.toGMTString()
}

const handleUserRouter = function(req,res) {
  const method = req.method
  if(method === 'GET' && req.path === '/api/user/login'){
    const { username, password } = req.query //从参数中取出用户名和密码
    const loginResult = loginTest(username,password) // loginTest是一个自己封装的函数,用来判断登录用户名和密码是否正确
    if(loginResult){ // 如果校验成功:那么就设置cookie,并且返回状态码为0,表示成功
      res.setHeader('Set-Cookie', `username=${username}; path=/; expires=${setCookieExpireTime()}`)
      return { 
        errorCode: 0,
        data: 'cookie设置成功'
      }
    }
    return { //否则校验失败,返回状态码-1
      errorCode: -1,
      msg: '用户名或密码错误'
    }
  } else { // else是对别的页面的请求
    if(req.cookie.username){ //如果存在这个cookie,允许放行
      return {
        errorCode: 0,
        msg: '已查询到cookie'
      }
    }
    return { //不存在这个cookie,那么就要先登录,设置cookie
      errorCode: -1,
      msg: '请登录'
    }
  }
}

module.exports = handleUserRouter
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛小y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值