Node.js用户登录:从cookie到session到redis

news/2024/5/18 16:39:37 标签: 前端, nodejs, cookie, redis, session

前言

当用户登录之后,需要标识用户的登录信息,用户在做其他操作的时候,比如电商系统中的添加购物车的功能,博客系统中的新建博客等都需要用户登录之后才可以操作,那如何才能标识用户已经登录呢?

cookie_2">cookie

cookie是存储在浏览器的一般字符串,最大5kb。

特点:

①存储在浏览器中
②跨域不共享
③存储格式:k1=v1;k2=v2,可以存储结构化数据
④每次发送http请求,会将请求域中的cookie一起发送给server
⑤server可以修改cookie并返回给浏览器
⑥浏览器也可以通过js修改cookie

cookie_14">浏览器查看cookie的方式

①F12中的Request Headers中的Cookie
Application中的Cookies
Console中输入document.cookie

cookie_19">Node.js操作cookie

app.js中解析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
})

user.js中设置cookie

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

data.name 是界面中的一个变量
path=/ 根路由
httpOnly 不允许前端修改cookie
expires设置过期时间,getCookieExpires是界面中的一个函数,获取下一天的时间

// 获取cookie的过期时间
const getCookieExpires = () => {
  const d = new Date()
  d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
  return d.toGMTString()
}

cookie_55">cookie的问题

①会暴露username等用户信息,较危险
②如果存储的内容过大,会放不下

session_58">session

session是存储在服务器端,所以没有容量限制。通常在客户端存储一个userid(标识),服务器端存储对应的用户信息。

session_60">Node.js操作session

app.js中解析session

// session 数据
const SESSION_DATA = {}

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

user.js中设置session

// data是SQL查出来的结果,把结果存储到session
req.session.username = data.username

session_88">session的问题

①目前session是js变量,放到node.js进程内存中,进程内存有限,访问内容有限会导致内存暴增
②如果线上多进程的话,进程之间内容无法共享

redis_91">redis

一个缓存数据库,数据存放在内存中,访问速度快,成本高,可存储数据量小

sessionredis_93">为什么session使用redis

session访问频繁,对性能要求高
②可以不考虑断电丢失数据的问题
③数据量不会太大

redis_97">redis使用方式

①npm下载redis
②创建客户端

// 引入redis
const redis = require('redis')

// 创建客户端
const redisClient = redis.createClient(端口号, 'ip地址')
redisClient.on('error', err => {
  console.error(err);
})

// 测试
redisClient.set('myname', 'helen1', redis.print)
redisClient.get('myname', (err, val) => {
  if (err) {
    console.error(err);
    return
  }
  console.log('val', val);
  // 退出
  redisClient.quit()
})

小结

cookiesessionredis,是一个不断优化的过程,cookie容量小且不安全所以有了session,但session无法实现内容共享,所以又使用了redis。不断更新的过程就是不断成长的过程。


http://www.niftyadmin.cn/n/1659452.html

相关文章

前端面试分享:冒泡排序和快速排序

前端面试过程中,某些公司对基础的算法也有一定的要求,比如常见的冒泡排序,快排等,今天我们就一起来看一下这两个排序算法。 冒泡排序 排序思想: 每次比较相邻的两个数,如果后一个比前一个小,则…

国内免费(开源)CMS内容管理系统介绍

最近在网上搜集了一下国内的CMS程序,包括了类型,脚本,及其特点和评价,希望能对大家有所帮助, 由于搜集于网络难免有不足和纰漏之处,还请大家能多多指正! 首先还是介绍一下什么是CMS。CMS&…

Javascript高级程序设计——12.基本包装类型

内容要点: 1、基本包装类型 2、Boolean类型 3、Number类型 4、String类型 背景: 为了便于操作基本类型的值,ECMAScript提供了3种特殊的引用类型:Booloean、String、Number 这些类型与其他引用类型相似,但却同时具…

JS数组去重方法整理,再也不用担心数组如何去重了

前端笔试的过程中,大概率会有这样一道题,给你一个字符串数组,让你输出其中不重复的字符串的个数,这就是典型的数组去重了,那应该如何进行数组去重呢?本篇文章整理了近10种方案,你来看看那个最适…

Javascript高级程序设计——13.内置对象

ECMA-262只定义了2个内置对象:Globel和Math 1、Global对象 表示全局变量,但该对象其实并不存在, 事实上,并不存在全局变量和全局函数:所有在全局作用于定义的变量和函数,都是Global对象的属性和方法 注意…

你需要知道的解决跨域的方案

今天我们再来分享一下关于跨域的问题,虽然之前也有分享过,但是解决方案不太全,且最近在面试的过程中,跨域是一个经典问题,所以我们需要知道其中的原理。 什么是跨域 跨域是浏览器的同源策略导致的。 什么是同源策略呢…

14.文件上传(小案例及解析)

1、php文件上传配置 a、file_uploadson/off; //确定服务器 b、upload_tmp_dirstring;//设置文件上传之前必须存放在服务器临时一个位置,知道文件移动到最终目的地位置。 c、max_execution_timeinteger; ///PHP脚本在注册一个致命错误之前可以执行的最长…

面经总结:何为Promise

Promise是ES6提供的对象,代表了未来将要发生的事件,用来传递异步操作的消息。Promise在开发和面试的过程中都很重要,下面我们一起来看一下关于Promise的相关知识。 Promise的状态 Promise对象代表一个异步操作,有三种状态&#x…