2025年1月3日更新
修改AllowCrossDomain.php
以支持多个域名
<?php
declare (strict_types = 1);
namespace app\middleware;
class AllowCrossDomain
{
/**
* 允许跨域的域名列表
*/
protected $allowOrigins = [
'http://yourapi1', //api1
'http://localhost:3000', // 本地开发环境
'http://localhost:5173', // Vite 默认端口
'http://127.0.0.1:3000',
'http://127.0.0.1:5173'
// 可以继续添加其他域名...
];
public function handle($request, \Closure $next)
{
$origin = $request->header('Origin');
if (in_array($origin, $this->allowOrigins)) {
header('Access-Control-Allow-Origin: ' . $origin);
header('Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Credentials: true');
}
if ($request->method(true) == 'OPTIONS') {
return response()->code(204);
}
return $next($request);
}
}
Access to XMLHttpRequest at 'http://yourapi' from origin 'http://localhost:5173' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.
这是一个 CORS(跨域资源共享)的问题。需要在前后端都进行相应配置。
1.后端 ThinkPHP 配置
在 ThinkPHP 中,你需要添加中间件来处理 CORS。创建一个新的中间件:AllowCrossDomain.php
<?php
declare (strict_types = 1);
namespace app\middleware;
class AllowCrossDomain
{
public function handle($request, \Closure $next)
{
header('Access-Control-Allow-Origin: http://localhost:5173');
header('Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Credentials: true');
// 预检请求直接返回空响应
if ($request->method(true) == 'OPTIONS') {
return response()->code(204);
}
return $next($request);
}
}
然后在配置文件middleware.php
中注册这个中间件:
<?php
return [
// 全局中间件定义
'global' => [
// ... 其他中间件
\app\middleware\AllowCrossDomain::class
]
];
2.前端 Vue/Axios 配置
修改你的 axios 配置:axios.js
import axios from 'axios'
const axiosInstance = axios.create({
baseURL: 'http://newsapi.xetx.top',
timeout: 5000,
withCredentials: true, // 如果需要携带 cookie
headers: {
'Content-Type': 'application/json',
}
})
// 请求拦截器
axiosInstance.interceptors.request.use(
config => {
const token = localStorage.getItem('accessToken')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
error => {
return Promise.reject(error)
}
)
export default axiosInstance
3.如果使用了 Vite
在 vite.config.js
中添加代理配置也是一个解决方案:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
'/api': {
target: 'http://newsapi.xetx.top',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
然后修改 axios.js
的 baseURL:
const axiosInstance = axios.create({
baseURL: '/api', // 改用代理地址
// ... 其他配置
})
这些配置完成后,CORS 问题应该就能解决了。记住:
- Access-Control-Allow-Origin 建议设置具体的域名,而不是 *
确保 Access-Control-Allow-Headers 包含了你需要的所有请求头 - 如果使用了 cookie,需要设置 Access-Control-Allow-Credentials: true
对于预检请求(OPTIONS),需要正确处理
如果还有问题,可以:
检查浏览器控制台的具体错误信息
确认后端接口是否正确响应 OPTIONS 请求
验证前端请求头是否正确设置