Home » Linux » 关于 307 重定向的研究
  • 28
  • 09月

关于 307 重定向的研究

主要应用场景:蜘蛛访问时,返回实际内容;其他客户端访问时通过 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 很像啊,是的,只是最后面几行有点区别。

Tags:   flaskphpcentos .