ThinkPHP6 - 综合笔记
跨域
jq 访问引发跨域,解决方式 3 步:
- 通过在路由中链式调用来设定一个或一组路由进行跨域,如
Route::get('apple', function(){return 'apple';})->allowCrossDomain();
或启用跨域中间件,该中间件框架已定义好,启用即可。启用方式是找到 app\middleware.php
文件,将框架预定义的中间件类加入进去
<?php
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
// \think\middleware\SessionInit::class
\think\middleware\AllowCrossDomain::class
];
- 如果有以下情况:
- 用到了自定义的 header
- 前端需要处理响应头
则可能需要修改预定义的中间件源码,或者自定义一个跨域中间件来用。举例:项目用到了 Authorization
头,且前端需要接收响应头中的该字段值并保存到本地,又不想修改源码,可以进行如下处理:
- 新建
app\middleware\MyCORSMiddleware.php
,使其继承框架AllowCrossDomain
- 覆盖
$header
,根据需要添加或修改内容
<?php
namespace app\middleware;
use think\middleware\AllowCrossDomain;
class CustomCORSMiddleware extends AllowCrossDomain
{
// 添加处理自定义请求头
protected $header = [
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => 1800,
'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With',
// 框架会拦截响应头,该字段作用允许输出响应头
'Access-Control-Expose-Headers' => 'Authorization'
];
}
- 在
app\middleware.php
中启用MyCORSMiddleware
<?php
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
// \think\middleware\SessionInit::class
// 使用自定义中间件
\app\middleware\CustomCORSMiddleware::class
];
- 调整对
OPTIONS
请求的处理
到这里部分前端请求还是可能引发跨域,可能的原因在于OPTIONS
依旧会进行完成流程的执行,因此在public\index.php
中增加对OPTIONS
请求的拦截,使其不进行后续任何处理,避免进入任何中间件、业务的执行,如
// [ 应用入口文件 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 处理 options 请求
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
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 后立即结束
exit;
}
// 执行HTTP应用并响应
$http = (new App())->http;
$response = $http->run();
$response->send();
$http->end($response);