五、cookie、session、token、localstroage、sessionStroage区别

一、localStorage 跟 sessionStorage有什么不同????

localStorage

1、生命周期:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。

2、储存大小: 5MB

3、获取方式:localStorage.getItem(“key”)

4、应用场景:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。

sessionStorage

1、sessionStorage的生命周期是仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。

1.1、只要这个浏览器窗口没有关闭,刷新、进入同源另一个页面,数据依然存在。
(同源:指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。 当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。)
(同源另一个页面:指 当前《页面1》为 localhost:8080,此时还没有存sessionStorage,再次打开一个《页面2》localhost:8080,《页面1》此时登录,sessionStorage.setItem 存储之后在《页面2》可以查看到存储信息,如果这时再打开《页面3》不会有存储的信息 )

1.2、但是 sessionStorage 在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。
《页面1》关闭,不会影响《页面2》的存储信息,如果重新打开《页面1》,sessionStorage存储的信息也被销毁

2、储存大小: 5MB

3、获取方式:sessionStorage.getItem(“key”)

4、应用场景:敏感账号一次性登录;

存在的问题:

“移动端sessionStorage缓存失效”,没错,就是概念没理解透,导致在App里面获取后为null,在PC端是正常的。

因为sessionStorage的生命周期是仅在当前会话下有效,移动端切换页面是关闭原页面打开新页面,知道sessionStorage特性的朋友看到这里是不是瞬间理解了?

解决方案,我们知道sessionStorage被清空的原因是:移动端切换页面是关闭原页面打开新页面,因此,在做移动端的时候,可以采用localStorage保存数据,使用完后再清空localStorage。

当然,如果是在同一个页面中,sessionStorage的使用是没有任何问题的。

二、session和cookie的区别是什么??

1、https://worktile.com/kb/p/38734
2、B站视频:B站终于有人将Session和cookie讲明白了!一节课彻底搞懂

Web3.0, 从1.0到3.0你不知道的互联网的演进史!

https://cloud.tencent.com/developer/article/1419229

Session 、Cookie和Token三者的关系和区别

参考链接:

session的使用

https://www.cnblogs.com/lihuidu/p/6495247.html

sessionID相当于一个文件名称, 里面存放的是

cookie的使用

1、cookie准备工作 前端页面(端口 8080)

<template>
  <div class="login">
    <h3>我在登录页面h3>
    <el-button v-if="isLoginFlag" @click="handleIsLogin('1')">我是免登录,我想直接跳转《结算页面》el-button>
    <el-button v-if="isLoginFlag" @click="handleIsLogin('2')">我是免登录,我想直接跳转《详情页面》el-button>
    <div v-if="isLoginFlag">
      我已经登录过了,现在有保存的cookie,可免登录
    div>
    <el-form v-else :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
      <el-form-item label="用户信息" prop="userInfo">
        <el-input v-model="ruleForm.userInfo" autocomplete="off">el-input>
      el-form-item>
      <el-form-item label="密码" prop="pass">
        <el-input type="password" v-model="ruleForm.pass" autocomplete="off">el-input>
      el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm('ruleForm')">登录el-button>
        <el-button @click="resetForm('ruleForm')">重置el-button>
      el-form-item>
    el-form>
  div>
template>

<script>
import axios from 'axios'
export default {
  name: 'login',
  data() {
    var validatePass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请再次输入密码'));
      } else if (value !== this.ruleForm.pass) {
        callback(new Error('两次输入密码不一致!'));
      } else {
        callback();
      }
    };
    return {
      isLoginFlag: false,
      ruleForm: {
        pass: '',
        userInfo: '',
      },
      rules: {
        pass: [
          { required: true, validator: validatePass, trigger: 'blur' }
        ],
        userInfo: [
          { required: true, message: '请输入用户信息', trigger: 'blur' }
        ],
      }
    };
  },
  created() {
    console.log('login-created')
    this.getUserInfo()
  },
  mounted() {
    console.log('login-mounted')
  },
  methods: {
    handleIsLogin(type) {
      if (type === '1') {
        this.$router.push({
          path: 'settlement',
        })
      } else {
        this.$router.push({
          path: 'details',
        })
      }
    },
    getCookieItem (sKey) {
      return (
        decodeURIComponent(
          document.cookie.replace(
            new RegExp(
              "(?:(?:^|.*;)\\s*" +
                encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") +
                "\\s*\\=\\s*([^;]*).*$)|^.*$",
            ),
            "$1",
          ),
        ) || null
      );
    },
    getUserInfo() {
      axios.get('http://localhost:3000/userInfo').then( res => {
        console.log('userInfo-54-->', res)
        // console.log('323', this.getCookieItem('tokenId'))
        document.cookie.split(';').forEach(item => {
          if (item.includes('tokenId')) {
            const pageToken = item.split('=')
            console.log('item=->', pageToken)
            if (pageToken.length > 0) {
              // 我登录了,不需要展示账号密码
              this.isLoginFlag = true
            } else {
              // 我的登录状态消失,需要输入账号密码
              this.isLoginFlag = false
            }
            this.setStroageUserInfo(pageToken)
            // console.log()
            // 为什么要用 localstroage 存储(sessionStroage),因为使用 store页面刷新就消失,跨页面我没法保存,初始化当前页面,保存的 cookie也会清空
            // 下次需要做的:
            // 怎么取cookie, document.cookie可以在这里获取,
            // 1、使用 localstroage 存储token
            // 2、研究 session
            // 3、cookie 相当于卡包,可以存多个key-value, Cookie不仅仅有名字和值两个属性,还有域(domain),过期时间(expires),路径(path)等属性。 其中,不同的域、不同的路径下可以存在同样名字的cookie。
            // 4、加油
          }
        })
      })
    },
    setStroageUserInfo(pageTokens) {
      console.log('123')
      if (pageTokens && pageTokens.length > 0) {
        console.log('2344')
        const token = pageTokens[0]
        localStorage.setItem('gzm-test-localStorage', 'gzm-localStorage-token')
        sessionStorage.setItem('gzm-test-sessionStorage', 'gzm-sessionStorage-token')
      }
    },
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          axios(
            {
              method: 'post',
              withCredentials: true, //只要添加withCredentials,请求的接口就报 CORS错误,
              url: 'http://localhost:3000/login',
              data: this.ruleForm
            }).then( res => {
            console.log('login-54-->', res)

            this.$router.push({
              path: 'details',
            })
            this.$message({
              showClose: true,
              message: '登录成功',
              type: 'success'
            });
          })
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
}
script>

<style>

style>

vue.config.js 配置

module.exports = {
  devServer: {
    host: '0.0.0.0',
    port: 8080,
    https: false,
    open: true,// vue项目启动时自动打开浏览器
    proxy: {
      '/api': { // '/api'是代理标识,用于告诉node,url前面是/api的就是使用代理的
          target: "http://localhost:3000", //目标地址,一般是指后台服务器地址
          changeOrigin: true, //是否跨域
          pathRewrite: { // pathRewrite 的作用是把实际Request Url中的'/api'用""代替
              '^/api': "" 
          }
      }
    }
  }
}

2、express搭建服务器(端口3000)

const express = require('express');
const fs = require('fs');
const app = express();
const port = 3000;
const path = require('path');


// 遇到的问题:1、使用axios请求express接口,code码返回 CORS 错误,服务器接口需要配置请求头,允许跨域
app.all("*",(req,res,next)=>{
  console.log('req--->', req.headers)
  // 遇到的问题:坑1、使用以下请求头,set-cookie之后,浏览器中的cookie中没有刚刚保存的cookie
  // 允许任何请求地址访问
	// res.setHeader("Access-Control-Allow-Origin", "*")
	// // 允许任何请求携带自定义数据访问
	// res.setHeader("Access-Control-Allow-Headers", "*")
  // 参考地址:https://blog.csdn.net/qq_54074878/article/details/125396455

  //解决坑 1 问题、
  res.header("Access-Control-Allow-Origin",req.headers.origin);//允许跨域的域名
  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");//允许跨域的请求方法
  res.header('Access-Control-Allow-Credentials', 'true');//Credentials 证书;凭证;证明;证件;文凭 允许携带cookie,设置这个的话上一条的设置不能为'*'
  res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");//允许的请求头部
	next()
})

app.post('/login', (req,res) => { 
  const data = fs.readFileSync('./HTTPInterface/login.json')
  res.setHeader('set-cookie', ['tokenId=FJOSDAFUEWOMRAKEFJSD343242DJOISFJSDFL;path=/;max-age=60;'])
  // 遇到的问题: 3、返回的数据乱码,可以添加请求头
  res.setHeader('Content-type', 'application/x-www-form-urlencoded')
  // setTimeout(() => {
    res.end(data);
  // },2000)
})

app.get('/userInfo', (req,res) => { 
  console.log('res-->', res)
  const data = fs.readFileSync('./HTTPInterface/userInfo.json')
  // 遇到的问题: 3、返回的数据乱码,可以添加请求头
  res.setHeader('Content-type', 'application/json')
  // setTimeout(() => {
    res.end(data);
  // },2000)
})

app.listen(port,() => {
  console.log(`Example app listening at http://localhost:${port})`)
})

参考文章:

https://www.freecodecamp.org/chinese/news/everything-you-need-to-know-about-cookies-for-web-development/

参考视频:

B站终于有人将Session和cookie讲明白了!一节课彻底搞懂
https://www.bilibili.com/video/BV1qu411Z745/?spm_id_from=333.337.search-card.all.click&vd_source=f069debb88bbe421f4c5b68e242f9165

cookie 是什么

Cookie 是一个 HTTP 请求标头,其中含有先前由服务器通过 Set-Cookie 标头投放或通过 JavaScript 的 Document.cookie 方法设置,然后存储到客户端的 HTTP cookie 。

这个标头是可选的,而且可能会被忽略,例如在浏览器的隐私设置里面设置为禁用 cookie。

为什么项目中要使用cookie,解决了什么问题

http是无状态协议,不会保存用户的登录信息,例如需求中需要购物,跳转到购物车/结算页面,没有用户登录信息,这时候解决方案就是 cookie,浏览器登录之后,服务器接受到,将cookie信息返回,并保存到页面, 可以设置cookie的有效期

1、cookie 是服务器生成,服务器可通过set-cookie设置cookie,
2、也可以在通过接口返回,比如接口详情信息中有cookie的标识
3、cookie 需要设置有效期,浏览器是否保存cookie是它的事

最后要合理使用cookie

cookie 中遇到哪些问题

问题一:跨域问题, 当本地开发服务器是http://localhost:8080,
访问的服务器地址是 http://localhost:300, 端口不同,产生跨域问题,

如何解决:首先页面接口会报一个错,参考图片 CORS.png
解决方案: 在axios中配置参数 withCredentials: true, 然后在 后端配置响应头 res.header(‘Access-Control-Allow-Credentials’, ‘true’);//Credentials 证书;凭证;证明;证件;文凭

问题二:如何返回json文件内容,
解决:通过fs.readFileSync,获取到文件
const data = fs.readFileSync(‘./HTTPInterface/login.json’)

问题三:后端使用express,设置set-cookie,注意 max-age=60(单位是秒)
res.setHeader(‘set-cookie’, [‘tokenId=FJOSDAFUEWOMRAKEFJSD343242DJOISFJSDFL;path=/;max-age=60;’])

cookie 中优势是什么

面试题 – 1、跨域请求如何携带cookie?

思考:???
参考文章:
https://juejin.cn/post/7066420545327218725

coocie为什么会跨域? 页面的服务器地址是:localhost:8080, 服务器地址是 localhost:3000, 当使用8080页面访问服务器登陆接口,就产生了跨域,此时有两个解决办法
参考文章:
https://www.cnblogs.com/imgss/p/cors.html

面试题 – 2、Cookie为什么会越来越大?

思考:???
因为cookie就像一个卡包,可以存放多个cookie,通一个页面可以创建多个cookie,过期时间跟设置的max-age有关

参考文章
https://juejin.cn/post/6844904113428234247

面试题 – 3、面试:彻底理解Cookie以及Cookie安全

思考:???
参考文章
https://juejin.cn/post/6844904102544031757?searchId=2023101220013497B9D88B9A81E66FAEB1

参考文章:
防止:CSRF攻击,举例

遇到哪些问题???

遇到的问题:1、使用axios请求express接口,code码返回 CORS 错误,服务器接口需要配置请求头,允许跨域

如何解决:首先页面接口会报一个错,参考图片 CORS.png
解决方案: 在axios中配置参数 withCredentials: true, 然后在 后端配置响应头 res.header(‘Access-Control-Allow-Credentials’, ‘true’);//Credentials 证书;凭证;证明;证件;文凭

遇到的问题:2、javascript模块中不能直接引入 const axios = require(‘axios’)

因为需要加入webpack模块化,要不然不认识
避开方案:可以使用 csdn 引入axios

遇到的问题:3、express如何设置 set-cookie

解决方案:
res.setHeader(‘set-cookie’, [‘token=fasdjfla;path=/;max-age=60*1000’])

遇到的问题:4、浏览器 http://localhost:8080 ,请求服务器 http://localhost:3000 登录接口,服务器 set-cookie,在浏览器不生效

解决方案:
因为浏览器在控制栏勾选了 「停用缓存」,所以导致cookie不会生效。

参考链接:https://blog.csdn.net/qq_54074878/article/details/125396455

问题5、设置max-age不生效,注意格式为 max-age,不是maxAge

解决:max-age=12000,直接设置某个值,不要用乘法
12 * 6000,因为请求头不会识别

问题6、服务器设置set-cookie,设置相同的path,请求头不会携带cookie

解答:浏览器不会自己携带cookie,需要用特殊的工具,或者前端自己关联 cookie,使用localstroage存储,
https://blog.csdn.net/HQqHQhqqhq/article/details/125906604

问题7、Cookie不仅仅有名字和值两个属性,还有域(domain),过期时间(expires),路径(path)等属性。 其中,不同的域、不同的路径下可以存在同样名字的cookie。

https://blog.csdn.net/z591102/article/details/107244500

你可能感兴趣的:(浏览器,前端,edge浏览器)