五、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