1. /config/cookie.php修改为
return [
'expire' => 0,
'path' => '/',
'domain' => '',
'secure' => false,
'httponly' => false,
'setcookie' => true,
// 正确的 CORS 头(开发环境)
'header' => [
'Access-Control-Allow-Origin' => 'http://localhost:1617',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Methods' => 'GET,POST,PUT,PATCH,DELETE,OPTIONS',
// 临时兼容:把 authori-zation 也放进来(注意是连字符+全小写)
'Access-Control-Allow-Headers' => 'authorization, Authorization, authori-zation, content-type, x-requested-with, if-modified-since, if-none-match, if-unmodified-since, form-type, cb-lang',
'Access-Control-Max-Age' => '1728000',
'Vary' => 'Origin',
],
'token_name' => 'Authorization',
];
2. public/index.php修改为
//允许跨域
// === CORS(支持凭证)开始 ===
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
// 允许的前端域名白名单(按你实际前端域名填写)
$allowOrigins = [
'https://0009.012539.cn',
'http://localhost:1617', // 本地调试可选
];
if ($origin && in_array($origin, $allowOrigins, true)) {
header("Access-Control-Allow-Origin: $origin");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Methods: GET,POST,PUT,DELETE,PATCH,OPTIONS");
header("Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization,X-Requested-With,Platform,token");
header("Vary: Origin"); // 让代理/缓存按来源区分
}
// 预检请求直接放行并返回 204(必须带上相同的 CORS 头)
if (strtoupper($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') {
http_response_code(204);
header("Content-Length: 0");
exit();
}
// === CORS 结束 ===
//end
3. VUE后台/src/libs/request.js
// src/libs/request.js
// +---------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +---------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +---------------------------------------------------------------------
import axios from 'axios';
import { Message } from 'element-ui';
import { getCookies, removeCookies } from '@/libs/util';
import Setting from '@/setting';
import router from '@/router';
// 用实例自己的默认项;把 withCredentials 放到实例里(很关键)
const service = axios.create({
baseURL: Setting.apiBaseURL,
timeout: 10000,
withCredentials: true, // ✅ 让跨域请求能带上 cookie
});
// ❌ 删掉这句(对实例没作用,而且容易误导):
// axios.defaults.withCredentials = true;
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 统一 baseURL;kefu 用 kefuapi
config.baseURL = config.kefu
? Setting.apiBaseURL.replace(/adminapi/, 'kefuapi')
: Setting.apiBaseURL;
// 上传文件时不要手动写 boundary,交给浏览器(可留可去)
// if (config.file) {
// config.headers['Content-Type'] = 'multipart/form-data';
// }
const token = getCookies('token');
const kefuToken = getCookies('kefu_token');
// 🚫 彻底清掉历史错别字请求头,避免被浏览器带出去
if (config.headers) {
delete config.headers['authori-zation'];
delete config.headers['Authori-zation'];
} else {
config.headers = {};
}
// ✅ 统一用标准 Authorization
const accessToken = config.kefu ? kefuToken : token;
if (accessToken) {
// 如果后端不需要 Bearer,就改成:config.headers['Authorization'] = accessToken;
config.headers['Authorization'] = `Bearer ${accessToken}`;
}
return config;
},
(error) => Promise.reject(error),
);
// 响应拦截器
service.interceptors.response.use(
(response) => {
// 兼容后端有时返回字符串的情况
const raw = response && response.data;
const obj = typeof raw === 'string' ? JSON.parse(raw) : (raw || {});
const code = obj.status ?? 0;
switch (code) {
case 200:
return obj;
// 登录失效(后台)
case 110002:
case 110003:
case 110004:
localStorage.clear();
removeCookies('token');
removeCookies('expires_time');
removeCookies('uuid');
router.replace({ name: 'login' });
return Promise.reject(obj);
// 客服登录失效
case 110005:
case 110006:
case 110007:
removeCookies('kefuInfo');
removeCookies('kefu_token');
removeCookies('kefu_expires_time');
removeCookies('kefu_uuid');
router.replace({ path: '/kefu' });
return Promise.reject(obj);
case 110008:
router.replace({ name: 'system_opendir_login' });
return Promise.reject(obj);
default:
return Promise.reject(obj || { msg: '未知错误' });
}
},
(error) => {
// 这里以前传了 undefined 进去导致 element-ui 报 “type” 错误
const msg =
error?.response?.data?.msg ||
error?.response?.data?.message ||
error?.message ||
'请求失败';
Message.error(msg);
return Promise.reject(error);
},
);
export default service;