共计 2739 个字符,预计需要花费 7 分钟才能阅读完成。
前后端拆散开发时,咱们的前端申请是跨域申请,会造成 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-cors | |
module.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-redis | |
module.exports = { | |
cors: { | |
enable: true, | |
package: 'egg-cors', | |
}, | |
redis: { | |
enable: true, | |
package: 'egg-redis', | |
}, | |
}; |
// config.default.js | |
config.redis = { | |
client: { | |
port: 6379, // Redis port | |
host: '127.0.0.1', // Redis host | |
password: '', | |
db: 0 | |
} | |
} |
应用 redis 设置值
// login.js | |
async 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 session | |
async 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 为跨域申请设置缓存状态, 咱们还能够设置定时工作, 删除该状态。
正文完