本文概述
- 1.下载GeoLite2免费数据库
- 2.安装MaxMind GeoIP2 PHP API
- 3.创建请求监听器
- 4.在services.yaml文件上注册事件监听器
本教程遵循上一篇文章的一些步骤, 其中我们解释了如何从Symfony 3中的访问者IP中检测城市, 国家和地区, 但进行了修改, 即应限制对整个网站的访问。
1.下载GeoLite2免费数据库 第一步, 你将需要项目中或在系统级别可访问的GeoLite二进制数据库。你可以从此处免费从官方的MaxMind GeoLite2下载数据库。在此页面中, 你需要注册一个GeoLite2帐户:
文章图片
创建帐户并按照通过电子邮件收到的步骤操作后, 你将可以私下下载MaxMind数据库, 在这种情况下, 我们将使用GeoLite2国家/地区版本:
文章图片
在本教程中, 我们将使用数据库并将其包含在我们自己的项目中的symfony项目的/ private目录中(请注意, 该目录不存在, 因此需要创建, 你可以根据以下内容更改数据库的路径:你的需求), 我们将使用数据库的国家/地区版本, 使我们能够获取本文中提到的信息, 特别是访问者IP的国家/地区。数据库是使用tar压缩的, 因此你可以使用以下命令从命令行提取其内容:
tar -xzf GeoLite2-Country_20200121.tar.gz
另外, 在Windows等其他操作系统中, 你也可以使用7Zip, Winrar或其他解压缩工具来提取其内容。现在你的项目中已有数据库, 目录结构应如下所示:
project/├── bin├── composer.json├── composer.lock├── config├── nbproject├── phpunit.xml.dist├── private/│└── geolite2-country/│├── COPYRIGHT.txt│├── GeoLite2-Country.mmdb│└── LICENSE.txt├── public├── src├── symfony.lock├── templates├── tests├── translations├── var└── vendor
2.安装MaxMind GeoIP2 PHP API 为了读取数据库, 你不需要托管在MySQL或其他数据库管理器中。数据库具有来自GeoIP的创建者的特殊格式, 即MaxMind DB。 MaxMind DB文件格式是一种数据库格式, 可以使用有效的二进制搜索树将IPv4和IPv6地址映射到数据记录。二进制数据库分为三个部分:
- 二进制搜索树。树的每个级别对应于IPv6地址的128位表示形式中的单个位。
- 数据部分。这些是针对特定IP地址返回给客户端的值, 例如” 美国” , “ 纽约” 或由多个字段组成的更复杂的地图类型。
- 数据库元数据。有关数据库本身的信息。
现在, 我们需要一种用于这种数据库格式的解析器。幸运的是, MaxMind团队为PHP编写了一个很棒的库, 该库使与数据库的交互变得非常容易, 并且你仅需几行代码就可以检索有关用户IP的地理信息。我们正在谈论的是MaxMind GeoIP PHP Api, 该软件包为GeoIP2 Web服务和数据库提供了API。该API还可以与免费的GeoLite2数据库(我们正在使用的数据库)一起使用。你可以使用运行以下命令的composer将此软件包安装在Symfony项目中:
composer require geoip2/geoip2
有关此库的更多信息, 请访问Github上的官方存储库。安装软件包后, 你将可以在Symfony的控制器上使用其类。
3.创建请求监听器 在每个Symfony应用程序上, 很多事情发生在幕后, 因此我们需要知道什么时候发生。 Symfony通过事件通知你何时发生这种情况, 它在处理HTTP请求时会触发与内核相关的多个事件。这正是我们要识别用户所在国家/地区并确定他是否应具有访问权限的地方。逻辑将如下所示, 在项目源的EventListener目录内创建一个RequestListener类。此类仅在构造函数中接收2个参数, 第一个是可以使用services.yaml文件中的%kernel.project_dir%变量注入到该类中的项目的绝对路径。第二个参数是模板引擎(Twig), 因此我们可以呈现一个视图, 该视图将通知用户该网站已被阻止。
此外, 该类将具有一个私有数组变量, 该变量将包含无法访问网站的国家/地区的ISO代码, 你可以根据自己的需要进行更新, 在本例中, 我们将仅阻止4个国家/地区:
- 哥伦比亚
- 巴西
- 玻利维亚
- 美国
<
?php// src/EventListener/RequestListener.phpnamespace App\EventListener;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;
// 1. Include GeoIp2 Classesuse GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
class RequestListener{// Store the absolute path of the project injected through the serviceprivate $projectDir;
/* @var $twig \Twig\Environment */private $twig;
/*** An array with all the ISO codes of the countries where the website shouldn't be accessible* * @var Array*/private $blacklist = ["CO", // Colombia"BO", // Bolivia"BR", // Brazil"US", // United States];
public function __construct(Environment $twigEnvironment, $projectDir){$this->
projectDir = $projectDir;
$this->
twig = $twigEnvironment;
}/*** Run the verification of the users country on every request.* * @param RequestEvent $event* @return type*/public function onKernelRequest(RequestEvent $event){if (!$event->
isMasterRequest()) {// don't do anything if it's not the master requestreturn;
}$this->
RestrictAccessOnDisallowedCountries($event);
}private function RestrictAccessOnDisallowedCountries(RequestEvent $event){/* @var $request \Symfony\Component\HttpFoundation\Request */$request = $event->
getRequest();
// Declare the path to the GeoLite2-City.mmdb file (database)$GeoLiteDatabasePath = $this->
projectDir . '/private/geolite2-country/GeoLite2-Country.mmdb';
// Create an instance of the Reader of GeoIp2 and provide as first argument// the path to the database file$reader = new Reader($GeoLiteDatabasePath);
// Check against the GeoLite database the user's country through his IPtry{// You can as well test with a fixed IP, for example one of USA in Minessota://$reader->
country('128.101.101.101');
// However for production, request the client ip://$reader->
country($request->
getClientIp());
/* @var $record \GeoIp2\Model\Country */$record = $reader->
country($request->
getClientIp());
$isoCode = $record->
country->
isoCode;
// If the obtained iso code matches with one of the blacklisted countries, block the access// rendering a custom pageif(in_array($isoCode, $this->
blacklist)){$response = new Response();
$response->
setStatusCode(Response::HTTP_FORBIDDEN);
// Render some twig view, in our case we will render the blocked.html.twig file$response->
setContent($this->
twig->
render("pages/blocked.html.twig", ['code' =>
$isoCode]));
// Return an HTML file$response->
headers->
set('Content-Type', 'text/html');
// Send response$event->
setResponse($response);
}} catch (AddressNotFoundException $ex) {// Couldn't retrieve geo information from the given IP// Is up to you if you want to block the access to the website anyway here ...}}}
请注意, 如果无法确定访问者所在的国家/地区, 此方法不会执行任何操作。如你所见, 在代码中, 我们呈现了以下Twig视图:
{# application/templates/pages/blocked.html.twig #}<
!DOCTYPE html>
<
html>
<
head>
<
meta charset="UTF-8">
<
title>
Website Blocked<
/title>
{% block stylesheets %}{% endblock %}<
/head>
<
body>
<
h1>
Access Disallowed<
/h1>
<
p>
This website doesn't work in your country ({{ code }})<
/p>
<
/body>
<
/html>
4.在services.yaml文件上注册事件监听器 最后, 为了启用事件监听器, 与自动装配的服务不??同, 你将需要在services.yaml文件上注册事件监听器, 如下所示:
# /application/config/services.yamlservices:App\EventListener\RequestListener:tags:- { name: kernel.event_listener, event: kernel.request }bind:$projectDir: '%kernel.project_dir%'
如步骤3所述, 我们将项目目录绑定为参数。就是这样!清除项目的缓存, 然后尝试通过VPN访问你的应用程序, 或为侦听器手动设置固定的ip, 然后检查地理封锁是否正常工作。
【如何在Symfony 5中将对网站的访问限制为特定国家(地理封锁)】快乐编码!
推荐阅读
- 如何解决Magento 2弃用问题(目录搜索当前已配置为使用已弃用的MySQL引擎。迁移到Elasticsearch引擎之一)
- 如何在Magento 2.3.2中重置测试销售/订单和仪表板信息
- 如何从Windows 10搜索中删除必应
- 如何在GoLang项目中迁移Go模块
- 如何在Ubuntu Desktop 18.04中安装KeePass 2
- 如何在Plesk的PHPMyAdmin上增加最大上传文件大小
- 如何在Paint.net中以SVG格式导入图像
- 如何使用JavaScript计算Google Maps中两个标记(坐标)之间的距离
- 无线网络技术专题全网最全!典型室内场景无线网络部署方案!