cookie

存储在客户端

优点

  1. 存储在客户端,不占用服务器资源

缺点

  1. 只能是字符串格式
  2. 存量有限
    1. sessionStorage (有大小限制(约10m)),不会自动发送给服务器
    2. localStorage (有大小限制(约10m)),不会自动发送给服务器
  3. 容易被获取
  4. 容易被篡改
  5. 容易丢失

session

存储在服务器

优点

  1. 可以是任何格式
  2. 存量理论上是无限的
  3. 数据难以被获取
  4. 数据难以篡改
  5. 不容易丢失

缺点

占用服务器资源

uuid universal unique identify 全球唯一id

session原理图

session原理示意图.jpg

session中间件

  1. 安装

npm i express-session@1.17.1

  1. 使用 ```json

const express = require(‘express’); const app = express();//创建一个以express应用,app实际上是一个函数,用于处理请求的函数 const path = require(‘path’); const rootPath = path.resolve(__dirname, ‘../public’); const cookieParser = require(‘cookie-parser’); const cors = require(‘cors’); const session = require(‘express-session’); const whiteApi = [‘http://localhost:3333‘]; // 使用session中间件 app.use(session({ secret: ‘lantong’, // 加密的字符串 name:’sessionId’ // 存储在本地session的名字,默认名字connect.sid })) // 设置cookieParser中间件 app.use(cors({ origin(origin, callback) { console.log(‘origin’, origin) if (whiteApi.includes(origin)) { callback(null, origin); } else { callback(new Error(“not allowed”)); } }, credentials: true })) // 使用跨域中间件

// 设置以后,会自动在req里面添加cookies属性,用于获取所有带来过来的cookies // 设置以后,会在res对象中注入cookie方法,用于设置cookie // app.use(cookieParser(‘1111’)) // 使用111对cookie加密 app.use(cookieParser()); app.use(require(‘./middlewares/tokenHandleware’)) // 设置跨域请求 // app.use(require(‘./middlewares/coresHandleware’))

/*

  • 发送请求的时,会根据请求的路径,从指定的目录中查找是否存在该文件,如果存在,则相应文件内容,而不再移交给后续的中间件,
  • 如果不存在文件,则直接移交给后续的中间件 */

app.use(express.static(rootPath, { index: ‘index.html’ //默认访问页面,默认值为index.html,可修改 })); // app.use(‘/static’, express.static(rootPath))// 也可以针对访问某个指定api路径,来标识需要 返回静态资源

/*

  • 默认res无法解析post请求的参数,也就是请求体
  • 使用该中间件后表示,当Content-Type是”application/x-www-form-urlencoded”,使用该中间件处理 / app.use(express.urlencoded({ extended: true })) /**
  • 默认res无法解析post请求的参数,也就是请求体
  • 使用该中间件后表示,当Content-Type是”application/json”,使用该中间件处理 */ app.use(express.json()) app.use(‘/api/admin’, require(‘./api/admin’)) // 除了api请求 app.use(‘/api/student’, require(‘./api/student’)) app.use(require(‘./middlewares/errMiddleware’)) // 处理所有的错误请求 app.listen(12306, () => { console.log(‘server on 12306 has started’) }) ```
  • secret: 'lantong' session用来加密的字符串,浏览器收到会保存在cookie里面
  • 使用express-session中间件以后,在req里面会注入session对象

image.png

服务器设置session

使用session中间件以后,req中会自动添加session对象

  1. const express = require('express');
  2. const router = express.Router();
  3. const { getResult } = require('./sendHelper');
  4. const AdminService = require('../../services/adminService');
  5. const crypter = require('../../util/crypt')
  6. router.get('/', (req, res, next) => {
  7. const { loginName, loginPwd } = req.query;
  8. AdminService.getAdminByLoginPwdAndLoginName(loginName, loginPwd).then(resp => {
  9. // res.header("set-cookie", `token=${resp.id};domain=localhost;path=/;max-age=3600;`);
  10. //1. 使用cookieheader做验证信息
  11. // const value = crypter.encrypt(resp.id.toString());
  12. // res.cookie('token', value, {
  13. // path: '/',
  14. // maxAge: 7 * 24 * 3600 * 1000, //此处是毫秒,
  15. // // signed: true 不适用cookie-parser自动加密
  16. // })
  17. // res.header('Authorization', value)
  18. //2. 使用session做验证信息
  19. req.session.loginUser = resp;
  20. res.send(getResult(resp))
  21. }).catch(err => next(err))
  22. })
  23. router.post('/', (req, res, next) => {
  24. AdminService.addAdmin(req.body).then(resp => {
  25. res.send(getResult(resp))
  26. }).catch(err => next(err))
  27. })
  28. module.exports = router;

服务端验证session

  1. const { pathToRegexp } = require('path-to-regexp');
  2. const ceyptor = require('../../util/crypt')
  3. const needTokenApi = [
  4. { method: 'GET', path: '/api/student' },
  5. { method: 'PUT', path: '/api/student/:id' }
  6. ]
  7. module.exports = function (req, res, next) {
  8. const apis = needTokenApi.filter(api => {
  9. return api.method === req.method && pathToRegexp(api.path).test(req.path);
  10. })
  11. if (apis.length === 0) {
  12. next();
  13. return;
  14. }
  15. //1. 使用cookieheader验证身份
  16. // let token = req.cookies.token || req.headers.Authorization; //未加密
  17. // console.log('req.cookies.token', ceyptor.decrypt(req.cookies.token)) // 解密token
  18. // // let token = req.signedCookies.token || req.headers.Authorization; 不使用,因为自动加密,header无法加密
  19. // if (!token) {
  20. // throw Error('you have not access the api');
  21. // }
  22. //2. 使用session验证身份
  23. console.log(req.session);
  24. if (req.session.loginUser) {
  25. next();
  26. } else {
  27. throw Error('you have not access the api');
  28. }
  29. }

session和cookie的关系

session是默认存在cookie里面的,所以需要设置客户端允许,携带cookie才会有效