在制作项目中,难免会遇到有跨域问题,需要增加指定响应头来满足跨域的需求。但ThinkPHP5.1版本的手册中,对跨域怎么设置提供的方法比较局限,所以这里经过研究,总结出了几种办法,推荐使用第三种。
一、路由
这方法是手册当中介绍的,这里简单复制下,深入了解可以查看手册。
如果某个路由或者分组需要支持跨域请求,可以使用
Route::get('new/:id', 'News/read')->ext('html')->allowCrossDomain();
Route::group('index', function() {
Route::get('new/:id', 'News/read');
})->prefix('index/')->allowCrossDomain();
这方法,仅适合定义了路由的情况下使用,如果是默认路由,这方法不适用。
二、header()函数
可以在入口文件index.php
、公共函数文件common.php
等文件里使用header()
函数定义跨域响应头。代码如下:
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE');
header('Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With');
header('Access-Control-Allow-Origin: *');
全局允许跨域的话,在入口文件或全局公共函数文件里增加跨域代码
单模块允许跨域的话,在模块公共函数文件里增加跨域代码
单控制器允许跨域的话,在控制器文件里增加跨域代码(命名空间与类声明之间区域)
单方法允许跨域的话,在方法代码开头增加跨域代码。或者使用路由设置跨域。
这个方法可能会存在响应头被覆盖的问题(框架输出响应内容时,设置了相同的响应头,后设置覆盖前设置)
三、中间件
可以使用中间件,更改响应输出内容。这种方法适合全局或部分模块使用。
创建application/http/middleware/AllowCrossDomain.php
文件,文件内容如下:
注意修改允许跨域的域名
<?php
namespace app\http\middleware;
/**
* 跨域中间件
* @package app\http\middleware
*/
class AllowCrossDomain
{
/**
* @param \think\Request $request
* @param \Closure $next
* @return mixed|\think\Response
*/
public function handle($request, \Closure $next)
{
// 允许跨域的域名
$allowOriginDomain = ['www.kancloud.cn', 'll00.cn'];
// HTTP请求头中的Origin
$origin = $request->header('origin', '');
// 附加响应头
$header = [];
if (!empty($origin)) {
$domain = explode('://', $origin)[1] ?? '';
if (in_array($domain, $allowOriginDomain)) {
$header['Access-Control-Allow-Credentials'] = 'true';
$header['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE';
$header['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With';
$header['Access-Control-Allow-Origin'] = '*';
}
}
return $next($request)->header($header);
}
}
在application/middleware.php
或application/index/middleware.php
文件加入
\app\http\middleware\AllowCrossDomain::class
示例:
<?php
return [
// 允许跨域
\app\http\middleware\AllowCrossDomain::class,
// 登录认证
//\app\wxamp\middleware\CheckLogin::class,
// 权限验证
//\app\wxamp\middleware\CheckPermission::class,
];
四、输出响应对象实例设置
可以在json()
、jsonp()
和xml()
等函数里设置跨域响应头,如:
return json(
[
'code' => 0,
'msg' => '操作成功',
],
200,
[
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE',
'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With',
'Access-Control-Allow-Origin' => '*',
]
);