ThinkPHP6使用中间件过滤来源网址或IP

技术 · 2023-06-21 · 2928 人浏览

使用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_REFERER'] : (isset($_SERVER['HTTP_ORIGIN']) ? $_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];

 

thinkphp 中间件