OpenResty动态地域定向:基于IP地址展示差异化页面

一、背景

根据用户的IP地址所在地理位置的不同,为用户提供差异化页面内容是一种常见的个性化策略,常用于实现地域定向、或提升用户体验等需求。为了实现这一功能,网站开发者通常会利用服务器端编程语言来检测访问者的地理位置,并据此展示相应的内容或重定向到特定的页面地址。
以下是一个简化的示例流程,说明如何在服务器端实现这一功能:
1、根据IP位置不同,返回不同的页面地址
南京地区,返回静态页面
其他地区,返回动态页面
2、指定如下user_agent 返回动态页面-(主要针对爬虫)
“xb-ios”,
“mgo-ios”,
“Baiduspider”,
“Googlebot”,
“yahoo”,
“YoudaoBot”,
“Sogou”,
“360Spider”,
“Sosospider”,
“YisouSpider”,
“msnbot”,
“bingbot”
3、 指定 如下IP地址,返回动态页面
“117.89.53.221”
“58.240.35.202”

二、openresty服务和模块安装

1、简介

OpenResty 是一个基于 Nginx 的平台和开发框架,它集成了 LuaJIT 和许多 Lua 库,使得开发者能够使用 Lua 语言编写 Nginx 模块,从而构建高性能的 Web 应用和微服务。
lua-resty-http 是一个 Lua 库,它为 OpenResty 提供了 HTTP 客户端功能,允许你在 Nginx 配置中或 Lua 脚本中发出 HTTP 请求。

2、安装

2.1、默认是已经安装好openresty服务(没有安装的小伙伴,可以直接去官网下载安装~)
官方地址:https://openresty.org/cn/download.html
2.2、lua-resty-http模块安装,后续lua脚本需要使用。安装方法如下(选择其中的一个)

  • 方法一、lua-resty-http yum安装
yum install perl-Digest-MD5
/usr/local/openresty/bin/opm get pintsized/lua-resty-http
  • 方法二、lua-resty-http 手动安装
wget https://github.com/pintsized/lua-resty-http/archive/master.zip
unzip master.zip
sudo cp -r lua-resty-http-master/lib/resty /usr/local/openresty/lualib/

三、获取IP地址库

完成openresty及其所需功能模块的配置后,接下来便是集成IP地址库以实现IP地址解析功能。当前市场上充斥着多种IP数据库选项,为开发者提供了广阔的选择空间。在作出决定时,重要的是要考量应用场景的具体需求、地理定位的精确度、查询速度以及预算限制等多个维度。

1、开源IP地址库:如MaxMind提供的GeoLite2是一个非常流行且免费的IP地理位置数据库。GeoLite2虽然在某些情况下可能不如商业产品精确,但对于多数一般需求来说已经足够。开发者可以通过定期检查或订阅更新通知来保持数据库的时效性。

2、付费IP地址纯真库:对于那些对数据准确性、实时性和全面性有高要求的应用场景,如金融、广告投放、网络安全监控等,建议选择更专业的付费IP地址库。这些服务通常承诺更高的查询速度、更低的延迟、更高的准确率以及更频繁的数据更新。

四、Nginx 配置文件

lua_package_path '/usr/local/openresty/lualib/?.lua;;';
resolver  114.114.114.114;
upstream www.opseye.com {
	server 120.55.52.63:80 max_fails=1 fail_timeout=5s;
}
server {
    listen       80;
    server_name  www.opseye.com opseye.com;
    access_log  /data/logs/1.log  main;
    error_log  /data/logs/1error.log  error;
    return 301    https://www.opseye.com$request_uri;
}
server {
    listen 443 ssl ;
    access_log /data/logs/1.log main;
    error_log  /data/logs/1error.log  error;
    server_name  www.opseye.com opseye.com;
    ssl_certificate   /usr/local/openresty/nginx/conf/ssl/www.opseye.com.pem;
    ssl_certificate_key /usr/local/openresty/nginx/conf/ssl/www.opseye.com.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location /lua {
            default_type text/html;
            content_by_lua_block {
                local args = ngx.req.get_uri_args()
                local ip = ngx.var.remote_addr
                local name = args.name or "World"
                ngx.say(ip .. "hello" .. name .. "!")
            }
    }
    location / {
        default_type 'text/html';
        content_by_lua_block {
            local http = require "resty.http"
            local httpc = http.new()

            local ip = ngx.var.remote_addr
            local user_agent = ngx.var.http_user_agent
            -- 定义需要重定向的 User-Agent 和 IP 地址
            local user_agents_to_redirect = {
                "xb-ios",
                "mgo-ios",
                "Baiduspider",
                "Googlebot",
                "yahoo",
                "YoudaoBot",
                "Sogou",
                "360Spider",
                "Sosospider",
                "YisouSpider",
                "msnbot",
                "bingbot"
            }
            local ips_to_redirect = {
                "117.89.53.221",
                "58.240.35.202"
            }
            -- 检查 User-Agent
            for _, agent in ipairs(user_agents_to_redirect) do
                if user_agent and user_agent:find(agent) then
                    ngx.exec("@dynamic_city")
                    return
                end
            end

            -- 检查 IP 地址
            for _, redirect_ip in ipairs(ips_to_redirect) do
                if ip == redirect_ip then
                    ngx.exec("@dynamic_city")
                    return
                end
            end
            local url = "https://c2ba.api.huachen.cn/ip?ip=" .. ip

            local res, err = httpc:request_uri(url, {
                method = "GET",
                headers = {
                    ["Authorization"] = "APPCODE aafabb"
                },
                ssl_verify = false,
                timeout = 5000,
                ca_cert_path = "/etc/pki/tls/certs/ca-bundle.trust.crt"
            })

            if not res then
                ngx.say("failed to request: ", err)
                return
            end
            -- 解析返回的JSON数据
            local cjson = require "cjson"
            local data = cjson.decode(res.body)

            if data.ret == 200 then
                local city = data.data.city
                -- 根据城市重定向
                if city == "南京" then
		    -- ngx.exec('@dynamic_city')
		     ngx.exec("@nj_static")
                else
		    ngx.exec('@dynamic_city')
                end
            else
                ngx.say("Error in API response")
            end
        }
    }
    location @nj_static {
            root /data/web/opseye.com;
            index index.html index.htm;
    }
    location @dynamic_city{
            add_header              backend $upstream_addr;
            proxy_set_header        Host $host:$server_port;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header        X-Forwarded-Proto $scheme;
            proxy_set_header        X-Forwarded-Host $host;
            proxy_set_header        X-Forwarded-Server $host;
            proxy_http_version 1.1;
            proxy_request_buffering off;
            proxy_ignore_client_abort on;
            client_max_body_size 100m;
            proxy_connect_timeout 600;
            proxy_send_timeout 600;
            proxy_read_timeout 600;
            proxy_pass http://www.opseye.com;
    }
}

五、测试

为了验证效果,我们特意选取了来自两个地域的IP地址对目标网址进行访问:一个是位于南京的IP,其得到的是一个静态网页;而所有其他地区的IP访问时,则收到了动态页面的内容。此外,当使用指定爬虫或特定IP地址进行请求时,系统同样呈现了动态页面,确保了测试的全面性与准确性。

  • 南京区域,返回静态页面:
    在这里插入图片描述

  • 其他区域,返回动态页面
    在这里插入图片描述

  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值