TP8 前后端跨域访问请求API接口解决办法
报错:Access to XMLHttpRequest at 'http://www.e.com/api/v1.index/index?t=1735897901267' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
实现目标:只要http://www.e.com/api/网址开关都充许跨域访问
像
http://www.e.com/api/xxx1
http://www.e.com/api/captchaController/generate
.....
不要一个一个接口写,希望有一个通用方法
跨域访问,都要发送 OPTIONS 请求
-
response()->code(204)
返回一个空的 HTTP 204 响应,这是处理 OPTIONS 请求的标准做法。
①是的OPTIONS 请求
③④是①OPTIONS 请求一定要返回的,不然不行
②是真实的请求
方法一:前端发起请求:不允许跨域携带cookie
1.0 前端发起请求代码
重点是这里:withCredentials: false // 不允许跨域携带cookie
$.ajax({
url: API.baseUrl + API.verifyCode2 + '?t=' + new Date().getTime(),
type: 'GET',
xhrFields: {
withCredentials: false // 不允许跨域携带cookie
},
beforeSend: function(xhr) {
// 添加自定义请求头
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
},
success: function(data) {
$('#verifyImg').attr('src', data.captcha);
verifyToken = data.token;
},
error: function(xhr, status, error) {
console.error('获取验证码失败:', error);
layer.msg('获取验证码失败,请刷新重试');
}
});
Tp8代码:
1.1 创建app\middleware/CorsMiddle.php代码
<?php
namespace app\middleware;
class CorsMiddle
{
public function handle($request, \Closure $next)
{
header('Access-Control-Allow-Origin: *'); // 或者指定具体域名
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Access-Control-Allow-Credentials: true');
if ($request->method() === 'OPTIONS') {
return response()->code(204);
}
return $next($request);
}
}
1.2 在app/middleware.php中加入
\app\middleware\CorsMiddle::class,
1.3 修改route/app.php的代码
// 处理 OPTIONS 预检请求
Route::options('api/*', function () {
return response()->code(204);
})->middleware(\app\middleware\CorsMiddle::class);
// 定义 API 路由组
Route::group('api', function () {
})->middleware(\app\middleware\CorsMiddle::class);
方法二:前端发起请求:允许跨域携带cookie
服务器的 Access-Control-Allow-Origin 必须是具体的域名,而不能是 *
2.1 前端发起请求
2.2 其它的TP代码是和方法一一样的,只要修改2.3步就行
2.3 修改app\middleware/CorsMiddle.php代码
<?php
namespace app\middleware;
class CorsMiddle
{
public function handle($request, \Closure $next)
{
// 从配置文件中获取允许的域名列表
// 允许的源
$allowedOrigins = [
'http://127.0.0.1:5500', // 本地开发环境地址
'http://localhost:5500', // 本地地址
'http://www.example.com', // 其他允许的域名
];
$origin = $request->header('Origin');
if (in_array($origin, $allowedOrigins)) {
header('Access-Control-Allow-Origin: '. $origin);
} else {
// 处理不允许的来源,例如返回403错误
return response()->code(403)->data(['message' => 'Forbidden']);
}
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Access-Control-Allow-Credentials: true');
if ($request->method() === 'OPTIONS') {
return response()->code(204);
}
return $next($request);
}
}
$allowedOrigins = [
'http://127.0.0.1:5500', // 本地开发环境地址
'http://localhost:5500', // 本地地址
'http://www.example.com', // 其他允许的域名
];
设置允许跨域的域名从配置文件中读取域名
2.4 改为在.env文件中读取
在.env文件加,然后修改app\middleware/CorsMiddle.php代码
#充许前端API跨域域名访问在这里设置 特别是前后端分离的 可以设置多个用逗号隔开
CORS_ALLOWED_ORIGINS=http://127.0.0.1:5500,http://www.e.com
<?php
namespace app\middleware;
class CorsMiddle
{
public function handle($request, \Closure $next)
{
// 从配置文件中获取允许的域名列表
// 允许的源
// $allowedOrigins = [
// 'http://127.0.0.1:5500', // 本地开发环境地址
// 'http://localhost:5500', // 本地地址
// 'http://www.example.com', // 其他允许的域名
// ];
// 从.env文件读取配置并转换为数组
$allowedOriginsStr = env('CORS_ALLOWED_ORIGINS', '');
$allowedOrigins = explode(',', $allowedOriginsStr);
$origin = $request->header('Origin');
if (in_array($origin, $allowedOrigins)) {
header('Access-Control-Allow-Origin: '. $origin);
} else {
// 处理不允许的来源,例如返回403错误
return response()->code(403)->data(['message' => 'Forbidden']);
}
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Access-Control-Allow-Credentials: true');
if ($request->method() === 'OPTIONS') {
return response()->code(204);
}
return $next($request);
}
}