- 28
- 09月
主要应用场景:蜘蛛访问时,返回实际内容;其他客户端访问时通过 307 重定向 到指定网站。
相关程序分为服务端和客户端两部分。
客户端环境: CentOS 6.x + LNMPA 。
注解
一定要是 LNMPA 环境,因为 .htaccess 是 Apache 特有的, Nginx 要实 现这部分规则,可能会比较复杂,目前没有深入研究,因此直接用 LNMPA 环境 。
目录
1 服务端
这里使用 Flask 来做服务端程序,熟悉嘛。
主要功能:通过 User-Agent 判断是不是蜘蛛,如果不是蜘蛛,则返回特定的 PHP 语句,并由客户端解析。
1.1 app.py
from flask import Flask, request, redirect
from werkzeug.useragents import UserAgent
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
_ua = UserAgent(request.form.get('HTTP_USER_AGENT', ''))
if _ua.browser not in ('google', 'yahoo', 'aol', 'opera', 'firefox'):
_r = '/redirect.php'
return '$_SERVER["REDIRECT_URL"]="%s";$httpcode=307;' % _r
return ''
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
注解
- $_SERVER["REDIRECT_URL"] 变量用于客户端判断是不是要重定向。
- $httpcode 变量用于辅助判断。
2 客户端
客户端程序分为静态网站和 WP 网站。
2.1 静态站点
静态网站主要增加下面 3 个文件:
2.1.1 .htaccess
重写规则,劫持 HTML 访问并转交 snippet.php 处理。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule .*\.(html?|php)$ snippet.php [L]
ErrorDocument 404 /snippet.php
</IfModule>
2.1.2 snippet.php
把客户端请求封装发送给服务端,服务端处理后,返回特定的字符串,字符串由 PHP 引擎进行解析。这个字符串有可能会包含 $_SERVER["REDIRECT_URL"] 变 量(内容为本地 URL 地址),若这个变量存在,则 include 这个变量中的 URL 地址( /redirect.php ), 进行 307 重定向。
<?php
session_start();
$postfields=array_merge($_SERVER, array("p"=>$_POST, "s"=>$_SESSION));
if (function_exists("curl_init")) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, count($postfields));
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_URL, "http://localhost:5000");
$e=curl_exec($ch);
$i=curl_getinfo($ch);
curl_close($ch);
}
else {
ini_set('default_socket_timeout', 2);
$o=array('http'=>array('method'=>'POST', 'timeout'=>'5', 'header'=>'Content-type: application/x-www-form-urlencoded\r\n', 'content'=>http_build_query($postfields)));
$s=stream_context_create($o);
$e=file_get_contents("http://localhost:5000", false, $s);
}
print_r($e);
eval($e);
if( isset($_SERVER["REDIRECT_URL"]) ) include( substr($_SERVER["REDIRECT_URL"],1) );
?>
2.1.3 redirect.php
上一步若 $_SERVER["REDIRECT_URL"] 存在,则会执行这个 PHP 文件,进行 重定向操作。
<?php
Header( "HTTP/1.1 307 Temporary Redirect" );
Header( "Location: http://m.fupiter.com" );
?>
2.2 WP 网站
对于 WordPress 不能使用 snippet.php ,因为 WP 伪静态需要使用 .htaccess 文件。不过还是有解决办法的,把下面的代码放到 index.php 的最前面:
2.2.1 index.php
<?php
session_start();
$postfields=array_merge($_SERVER, array("p"=>$_POST, "s"=>$_SESSION));
if (function_exists("curl_init")) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, count($postfields));
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_URL, "http://localhost:5000");
$e=curl_exec($ch);
$i=curl_getinfo($ch);
curl_close($ch);
}
else {
ini_set('default_socket_timeout', 2);
$o=array('http'=>array('method'=>'POST', 'timeout'=>'5', 'header'=>'Content-type: application/x-www-form-urlencoded\r\n', 'content'=>http_build_query($postfields)));
$s=stream_context_create($o);
$e=file_get_contents("http://localhost:5000", false, $s);
}
print_r($e);
eval($e);
if( isset($_SERVER["REDIRECT_URL"]) && $httpcode==307) {
Header( "HTTP/1.1 307 Temporary Redirect" );
Header( "Location: http://t.fupiter.com" );
exit;
}
?>
这部分代码是不是和 snippet.php 很像啊,是的,只是最后面几行有点区别。