前后端拆散开发时,咱们的前端申请是跨域申请,会造成session和cookie生效的问题。
在浏览多种解决办法后,我抉择了应用redis来实现session的解决方案,确保前端应用跨域申请的状况下,后端能够维持用户session.
起因
为什么抉择redis来实现跨域下的session呢?
我浏览了多种跨域session失落的解决办法,但都没有失效,于是最初抉择了redis才解决了这个问题。
前后端增加credential后,浏览器无奈主动加载第三方cookie, 服务端的session和cookie依然失落。
前端Fetch跨域申请
const data = {key:"value"};// 参数const myHeaders = new Headers();myHeaders.append('Access-Control-Allow-Origin', 'http://localhost:3000/'); // 设置Access-Control-Allow-Credentials,跨域申请带受权myHeaders.append('Access-Control-Allow-Credentials', 'true'); // 设置mode为cors,进行跨域申请myHeaders.append('mode', 'cors'); // 设置Content-Type, 参数格局myHeaders.append('Content-Type', 'application/x-www-form-urlencoded')var urlencoded = new URLSearchParams()for (let key in data) { urlencoded.append(key, data[key])}const requestOptions = { method: 'POST', headers: myHeaders, body: urlencoded, redirect: 'follow', // 设置为include确保跨域申请放弃cookie credentials: 'include', }fetch(api, requestOptions).then(response=>response.json());
Egg跨域配置
// config.default.js'use strict'const path = require('path')module.exports = appInfo => { const config = { mode: 'file', errorHandler: { match: '/' }, } // 设置security里的csrf敞开,容许跨域申请 config.security = { domainWhiteList: ['*'], csrf: { enable: false } } // 设置cors插件配置, origin为前端的起源(带credentials无奈设置为*) // 设置credentials为true,返回的Header带有Access-Control-Allow-Credentials为true config.cors = { origin: 'http://localhost:3000', credentials: true, allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH' } // 这里设置egg自带的session,但跨域申请依然失落session config.session = { key: 'WheelFit', maxAge: 30 * 24 * 3600 * 1000, // 30 days httpOnly: true, encrypt: true, renew: true } // 自定义中间件, sessionToken为鉴权中间件,在收到申请后获取session里存储的token config.middleware = ['sessionToken', 'errorHandler'] return { ...config, }}
// plugin.js'use strict';// 增加cors插件用于回复跨域申请// npm i --save egg-corsmodule.exports = { cors: { enable: true, package: 'egg-cors', }};
这个配置是在其余的解决跨域session失落问题的文章中找到的,实践上增加credientals即可放弃session,但我这里并没有失效,跨域申请依然会失落session,并且给response设置的cookie也不能被浏览器获取到。然而应用postman,发送非跨域申请,是能够记录的session的。
无奈我只能抉择应用redis维持跨域申请的session
Redis 配置
前端Fetch申请依然放弃不变(尽管credential曾经不须要设置)
后端须要新增egg-redis插件
// plugin.js'use strict';// 增加cors插件用于回复跨域申请// npm i --save egg-cors// npm i --save egg-redismodule.exports = { cors: { enable: true, package: 'egg-cors', }, redis: { enable: true, package: 'egg-redis', },};
// config.default.jsconfig.redis = { client: { port: 6379, // Redis port host: '127.0.0.1', // Redis host password: '', db: 0 }}
应用redis设置值
// login.jsasync login(){ const {ctx} = this; // login operation // login successfully const token = generateToken(); ctx.app.redis.set(`token${userid}`, token); return (ctx.body={success:true, userid: userid})}// check sessionasync session_token() { const {ctx} = this; const {userid, token} = ctx.request.body; const redis_token = ctx.app.redis.get(`token${userid}`); if(redis_token === token) { return (ctx.body={success: true}); } return (ctx.body={success: false});}
这样咱们在服务端应用redis为跨域申请设置缓存状态,咱们还能够设置定时工作,删除该状态。