使用ThinkPHP6开发接口时会遇到前置过滤或判断,我们可以使用中间件功能。以下是单应用模式示例:
第1种方式,命令行方式:
php think make:middleware Filter
第2种方式,手动在`app`目录下创建`middleware`文件夹,再创建中间件类:
<?php
namespace app\middleware;
class Filter
{
public function handle($request, \Closure $next, $name)
{
//to do
return $next($request);
}
}
需要我们配置好白名单网址和白名单IP,在.env配置文件中增加以下配置:
[FILTER]
HOST = localhost,127.0.0.1,abc.com
IP = 127.0.0.1,192.168.0.253
to do中实现过滤来源网址逻辑,失败时返回错误Json。
//来源网址
$origin = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_ORIGIN'] : '';
if($origin != '') {
$list = env('filter.host', '');
$lists = explode(',',$list);
for ($i = 0;$len = count($lists),$i < $len;$i++) {
if(strpos($origin,$lists[$i]) !== false) {
$flag = true;
break;
}
}
}
if(!$flag) {
return json(["errorCode" => 9998,"errorMessage" => '请求来源不正确']);
}
再进一步,增加来源IP判断
//来源IP
$ip = '';
if(isset($_SERVER["HTTP_CLIENT_IP"])) {
$ip = $_SERVER["HTTP_CLIENT_IP"];
}
else if(isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else if(isset($_SERVER["REMOTE_ADDR"])) {
$ip = $_SERVER["REMOTE_ADDR"];
}
if(filter_var($ip,FILTER_VALIDATE_IP)) {
$list = env('filter.ip', '');
$lists = explode(',',$list);
for ($i = 0;$len = count($lists),$i < $len;$i++) {
if(strpos($ip,$lists[$i]) !== false) {
$flag = true;
break;
}
}
}
整个中间件逻辑代码如下:
public function handle($request, \Closure $next)
{
$flag = false;
//来源网址
$origin = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_ORIGIN'] : '';
if($origin != '') {
$list = env('filter.host', '');
$lists = explode(',',$list);
for ($i = 0;$len = count($lists),$i < $len;$i++) {
if(strpos($origin,$lists[$i]) !== false) {
$flag = true;
break;
}
}
}
if($flag) {
//来源IP
$ip = '';
if(isset($_SERVER["HTTP_CLIENT_IP"])) {
$ip = $_SERVER["HTTP_CLIENT_IP"];
}
else if(isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else if(isset($_SERVER["REMOTE_ADDR"])) {
$ip = $_SERVER["REMOTE_ADDR"];
}
if(filter_var($ip,FILTER_VALIDATE_IP)) {
$list = env('filter.ip', '');
$lists = explode(',',$list);
for ($i = 0;$len = count($lists),$i < $len;$i++) {
if(strpos($ip,$lists[$i]) !== false) {
$flag = true;
break;
}
}
}
}
if(!$flag) {
return json(["errorCode" => 9998,"errorMessage" => '请求来源不正确']);
}
return $next($request);
}
如果所有控制器都需要使用这个中间件过滤,则在`app\middleware.php`中增加:
\app\middleware\Filter::class
如果只有需要的控制器才使用这个中间件过滤,则可以在需要的控件器类中增加:
//此类使用中间件
protected $middleware = [Filter::class];