vue 中设置了instance.defaults.withCredentials = true; 无法请求后端问题解决

个人理解

# post携带cookie需要前后端配合 然而 post请求会优先发送一个预检(检查请求是否安全)。

我们大部分会在请求拦截是否是登录状态 这就导致乌龙出现了 由于预检的时候不会携带cookie会被后端直接拦截而无法成功预检所以只需要加上以下代码就可以解决(我的预检用的都是OPTIONS方法 具体为什么你们可以自己了解 。。。)

前面说了cookie需要前后的配合 如果后端不设置请求头也是不行的

这样应该就可以解决你的问题了

以下为原始文件,哪里需要调整: import axios from 'axios' import { ElMessage, ElLoading } from 'element-plus' //http请求参数 const httpConfig = { isRefreshing: false, //是否正在刷新的标记 loadingInstance: null, //加载效果实例 requests: [] //重试队列,每一项将是一个待执行的函数形式 } /* *请求封装 *参数示例 useHttp({method:'get',url:'auth/login',data:...}) *@params {method,url,data,loading,beforeSend,progress,success,successMsg,error,complete} */ export const useHttp = (params) => { //获取配置变量 const router = useRouter() const runConfig = useRuntimeConfig() //获取token const tokens = useToken().token //获取axios实例 const instance = axios.create() instance.defaults.baseURL = runConfig.public.baseURL instance.defaults.timeout = runConfig.public.timeout instance.defaults.headers = {'content-type': 'application/json'} //如果有token带上 if(tokens && tokens.accessToken) { instance.defaults.headers.Authorization = `Bearer ${tokens.accessToken}` } //标准化参数 params.method = params.method ? params.method.toLowerCase() : 'get' //axios响应拦截器 instance.interceptors.response.use(response => response, async error => { const resp = error.response const originalRequest = error.config if (resp?.status === 401 && resp?.headers['token-expired']) { //如果正在刷新,进入队列 if (!httpConfig.isRefreshing) { const refreshConfig = error.config httpConfig.isRefreshing = true return new Promise((resolve, reject) => { axios({ method: 'post', url: `${runConfig.public.baseURL}/auth/retoken`, headers: {'content-type': 'application/json'}, data: {'refreshToken': tokens.refreshToken} }) .then(async(res) => { useToken().set(res.data.accessToken, res.data.refreshToken) //存储Token const newToken = res.data.accessToken refreshConfig.headers.Authorization = `Bearer ${newToken}` //重新发送队列中的请求 httpConfig.requests.forEach((cb) => cb(newToken)) httpConfig.requests = [] resolve(axios(refreshConfig)) //直接用axios实例 }).catch(async(err) => { //通知队列状态 httpConfig.requests.forEach((cb) => cb(null)) httpConfig.requests = [] //刷新token失败,跳转到登录页面 process.client && ElMessage.error('认证失败,请重新登录') await router.push('/account/login') reject(err) }).finally(() => { httpConfig.isRefreshing = false }) }) } else { return new Promise((resolve, reject) => { httpConfig.requests.push((newToken) => { if(newToken) { originalRequest.headers.Authorization = `Bearer ${newToken}` resolve(axios(originalRequest)) //直接用axios实例 } else { reject(error) } }) }) } } //401没有权限或403刷新token失败 else if(resp?.status === 401 || resp?.status === 403) { //process.client && ElMessage.warning('登录失效,请重新登录') useToken().remove() await router.push('/account/login') } return Promise.reject(error) }) //成功回调 const handleSuccess = (res) => { const message = { status: res.status, contentType: res.headers['content-type'], pagination: res.headers['x-pagination'] ? JSON.parse(res.headers['x-pagination']) : {}, data: res.data } //成功消息(服务端禁用) if (process.client && params.successMsg) { ElMessage.success(params.successMsg) } if(params.success) { params.success(message) } return message } //错误回调 const handleError = async(error) => { const resp = error.response const message = { status: resp?.status, message: resp?.data?.message ? resp?.data?.message : error.message, data: null } if(resp.data instanceof Blob) { //将 Blob 转换为文本 const errorText = await error.response.data.text() //解析 JSON 错误信息 const errorData = JSON.parse(errorText) message.message = errorData.message } //请求超时 if(error.code == 'ECONNABORTED' && error.message.includes('timeout')) { process.client && ElMessage.error(`请求超时,建议更换网络后重试`) } //网络错误(服务端禁用) else if (!resp) { process.client && ElMessage.error(`语法错误:${error}`) } //400:响应错误(服务端禁用) else if (resp.status === 400) { process.client && ElMessage.warning(message.message) } //415:请求方式有误(服务端禁用) else if (resp.status === 415) { process.client && ElMessage.warning("请求类型有误,请检查重试") } //422:数据验证未通过(服务端禁用) else if (resp.status === 422) { process.client && ElMessage.warning('数据验证未通过,请检查重试') } //500:响应错误(服务端禁用) else if (resp.status === 500) { process.client && ElMessage.error('服务器通讯异常,请稍候再试') } //错误回调 if(params.error) params.error(message) return message } //抛出实例调用 return new Promise((resolve, reject) => { let config = {} config.url = params.url config.method = params.method //响应的数据类型 if(params.responseType) { config.responseType = params.responseType || 'json' } //上传文件 if(params.method === 'file') { config.method = 'post' config.headers = { 'content-type': 'multipart/form-data' } config.onUploadProgress = params.progress } //下载文件 if(params.method === 'down') { config.method = 'get' config.responseType = 'blob' config.onDownloadProgress = params.progress } if(params.data) config.data = params.data //加载ElLoading(服务端禁用) if(process.client && params.loading && !httpConfig.loadingInstance) { httpConfig.loadingInstance = ElLoading.service({ body: true, lock: true }) } //请求前调用 if(params.beforeSend) params.beforeSend() //发送请求 instance.request(config).then(res => { //成功回调 resolve(handleSuccess(res)) }).catch(error => { //错误回调 reject(handleError(error)) }).finally(() => { //完成调用 if(params.complete) params.complete() if (httpConfig.loadingInstance) httpConfig.loadingInstance.close() }) }) }
最新发布
10-03
//定制请求的实例 //导入axios npm install axios import axios from 'axios'; import { ElMessage } from 'element-plus' //定义一个变量,记录公共的前缀 , baseURL //const baseURL = 'http://localhost:8080'; const baseURL = '/api'; const instance = axios.create({ baseURL }) import {useTokenStore} from '@/stores/token.js' //添加请求拦截器 instance.interceptors.request.use( (config)=>{ //请求前的回调 //添加token const tokenStore = useTokenStore(); //判断有没有token if(tokenStore.token){ config.headers.Authorization = tokenStore.token } return config; }, (err)=>{ //请求错误的回调 Promise.reject(err) } ) /* import {useRouter} from 'vue-router' const router = useRouter(); */ import router from '@/router' //添加响应拦截器 instance.interceptors.response.use( result => { //判断业务状态码 if(result.data.code===200){ return result.data; } //操作失败 //alert(result.data.msg?result.data.msg:'服务异常') ElMessage.error(result.data.msg?result.data.msg:'服务异常') //异步操作的状态转换为失败 return Promise.reject(result.data) }, err => { //判断响应状态码,如果为401,则证明未登录,提示请登录,并跳转到登录页面 if(err.response.status===402){ ElMessage.error('请先登录') router.push('/login') }else{ ElMessage.error('服务异常') } return Promise.reject(err);//异步的状态转化成失败的状态 } ) export default instance;前端部署 配置生产和开发环境 在项目打包之前,先配置myAxios.ts文件(这个文件就是你自定义axios的文件,并且在里面区分开发环境和生产环境)的线上环境和生产环境。(注意生产环境的url后面要加上后端端口号,但有时又不要加,视情况而定。) import axios from 'axios'; const isDev = process.env.NODE_ENV === 'development'; const myAxios = axios.create({ baseURL: isDev ? 'http://localhost:8080/api' : 'http://你的服务器IP地址或者域名/api', }) myAxios.defaults.withCredentials = true; //设置true // Add a request interceptor myAxios.interceptors.request.use(function (config) { console.log('我要发请求啦') return config; }, function (error) { return Promise.reject(error); }); myAxios.interceptors.response.use(function (response) { console.log('我收到你的响应啦') // 未登录则跳转登录页 if (response?.data?.code === 40100) { const redirectUrl = window.location.href; window.location.href = `/user/login?=redirect=${redirectUrl}`; } return response.data; }, function (error) { // Do something with response error return Promise.reject(error); }); export default myAxios; 前端项目打包 在宝塔部署前端项目之前,先将前端项目打包好。在package.json文件中执行buid命令。 打包后会多出一个dist目录,点击右键打开于终端,在终端中执行serve命令,判断打包好的项目是否能够运行成功。(注意一定要切换至dist目录下执行serve命令,不然点击链接显示不出来项目) 点击Local后面的地址,看看项目打包是否有问题。 如果是这样子的话就没啥问题。(我这个显示了当前登录用户“ikun”,是因为我已经上线了,你们是不会显示的) 分析一下,给出详细的步骤我需要知道哪个文件在哪个位置需要修改什么都指出来
03-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值