我在开发过程中遇到这两个问题,找了很多贴子但是都没解决我的问题.
一个偶然,让我走出困境,
问题
- axios跨域请求
- axios每次请求session都在不停变化
解决办法
- axios使用代理服务解决跨域
- axios+vue请求时携带cookie,来解决axios每次请求session都不停变化
axios跨域
封装axios为http.js,将http.js在main.js
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
// import store from '@/store'
// import { getToken } from '@/utils/auth'
// 创建一个独立的axios实例
const http = axios.create({
// baseURL: '', // url = base url + request url
// // withCredentials: true, // send cookies when cross-domain requests
// // request timeout
// timeout: 7000,
// 为了携带cookie保持session的唯一性
withCredentials: true,
// crossDomain: true
baseURL: '', // 通过/api别名指定后端路由,这里什么都不要写
timeout: 5000,
headers:{},
// 不知道有什么用
// crossDomain:true
})
// 添加请求拦截器
axios.interceptors.request.use(
function(config) {
// do......
console.log('请求拦截1')
// 判断token是否存在,并且设置接口白名单
// Message({
// message: '正在发送请求',
// type: "success"
// })
// 在发送请求之前进行操作
return config
},
function(error) {
// do......
console.log('请求拦截2')
// 对请求错误进行操作
return Promise.reject(error)
}
)
// 添加响应拦截器
axios.interceptors.response.use(
function(response) {
console.log('请求拦截3')
const code = response.data.code;
if(code !== 10000) {
Message({
message: `请求发送错误:${code} ${response.data.msg}`,
type: 'error'
})
} else {
Message({
message: '请求成功',
type: 'success'
})
}
// 对响应数据进行操作
return response
},
function(error) {
Message({
message: `请求发生错误:${error}`,
type: 'error'
})
console.log('请求拦截4')
// 对响应错误进行操作
return Promise.reject(error)
}
)
export default http
不方便封装的情况加,或者在main.js中添加
// 意思是携带cookie信息,保持session的一致性
axios.defaults.withCredentials = true
跨域
一定一定要注意的是,修改后一定要重启项目,否则不生效!!!
vue.config.js文件
devServer: {
proxy: {
'/api': {
/*
* 很好理解,就是将请求地址的首个/看成 http://127.0.0.1:3000/
* 例如: 请求 http://localhost:3000/api/object/session 可写成
* axios({method: 'get',url: "/api/object/session",data: {},})
* */
target: 'http://127.0.0.1:3000/api/',// 后端接口
changeOrigin: true, // 是否跨域
// pathRewrite这个值完全可以不要
pathRewrite: {
//这里理解成用‘/api’代替target里面的地址,组件中我们调接口时直接用/api代替,完全是累赘
'^/api': ''
}
}
},
port: port,
// open: true,
overlay: {
warnings: false,
errors: true
}
},
koa2后端
其他语言后端同理设置即可
/**
* 解决跨域
*/
app.use(async (ctx, next) => {
// 绝对不能使用 * ,使用 * 后无法获取cookie
ctx.set('Access-Control-Allow-Origin', ctx.headers.origin);
// http://localhost:9712/
// ctx.set('Access-Control-Allow-Origin', 'http://localhost:9712');
ctx.set('Access-Control-Allow-Headers', 'content-type');
// 指定允许的跨域请求方法。可同时设置多个方法,多个方法用英文逗号(,)分隔。
ctx.set('Access-Control-Allow-Methods', 'OPTIONS,GET,HEAD,PUT,POST,DELETE,PATCH')
ctx.set('Access-Control-Allow-Credentials', true);
// https://blog.csdn.net/qq_37301074/article/details/126037500
// header("Set-Cookie:PHPSESSID=".session_id()."; HttpOnly;Secure;SameSite=None");
// ctx.set("Set-Cookie","SameSite=None;Secure")
// ctx.set(
// 'Access-Control-Allow-Headers',
// 'token,Content-Type,Content-Length, Authorization, Accept,X-Requested-With,domain,zdy' //当客户端跨域并需要传递cookie时,需要设置Access-Control-Allow-Headers,并且值为不能为“*”,需要具体配置 代表允许上传的请求头字段
// )
await next();
});
设置session
/**
* 配置 session
* 官方: https://www.npmjs.com/package/koa-session
* 教程: https://www.jianshu.com/p/86d43aca5cec
*/
const session_config = {
/** cookie的key。 (默认是 koa:sess) */
key: 'msg',
/** session 过期时间,以毫秒ms为单位计算 。*/ // 1000ms = 1s
maxAge: (1000 * 60) * 60 * 2,// 2 小时过期
// maxAge: 1000 * 2,
/** 自动提交到响应头。(默认是 true) */
autoCommit: true,
/** 是否允许重写 。(默认是 true) */
overwrite: true,
/** 是否设置HttpOnly,如果在Cookie中设置了"HttpOnly"属性,那么通过程序(JS脚本、Applet等)将无法读取到Cookie信息,这样能有效的防止XSS攻击。 (默认 true) */
httpOnly: true,
/** 是否签名。(默认是 true) */
signed: true,
/** 是否每次响应时刷新Session的有效期。(默认是 false) */
rolling: true,
/** 是否在Session快过期时刷新Session的有效期。(默认是 false) */
renew: false,
// 测试
// httpOnly: false,
};
const session = require('koa-session');
app.keys = ["12345"] // session加密字段 // 这个是配合signed属性的签名key
app.use(session({...session_config}, app))
结果
添加一个计数器
// 一个简单的计数器返回,访问 http://localhost:3000 每次数字都会 +1
app.use(async (ctx, next) => {
var session = ctx.session;
session.count = session.count || 0;
session.count++;
ctx.body = ctx.session
// ctx.body = ctx.session.counter;
})
很明显计数不为1即为解决axios每次请求session都在不停变化,而web端口和服务器端口不一致,接口调用即为跨域成功.