月度归档:2014年02月

去除http头部的Referer信息,防止重要网址被浏览器“偷偷的泄漏”

有时候我们需要在点击链接时候去除http头部的referer属性,
比如在网站后台有链接到外部网站的地方,若不去除的话
很容易暴漏我们的后台地址
浏览器 我只测试了IE8以及chrome33

通常下面的一些方式,$_SERVER[‘HTTP_REFERER’] 会无效:
1.直接输入网址访问该网页。
–!肯定不能让用户复制链接然后在粘贴打开吧

2.Javascript 打开的网址。

<a href="javascript:void(0)" onclick="window.open('/test/index.php?a');">window.open()</a>

IE8没有问题,但是chrome还是携带referer

3.Javascript 重定向(window.location)网址。

<a href="javascript:void(0)" onclick="location='/test/index.php?a'">location</a><br/>

 

表现与使用open()一样
看样子chrome只要js代码在a标签的点击事件中就会携带referer信息

4.使用html5中noreferrer

<a href="/test/index.php?noreferer" rel="noreferrer" target="_blank">noreferrer</a>

很明显IE8以及以下肯定是不支持的
chrome正常点击的话没问题,但是假如是右击链接然后重新窗口或标签打开,同样会传递referer
操作性:4 稳定性:3 兼容性:3

5.使用 meta refresh 重定向的网址。
这个会多出来个跳转页面,
IE8支持,chrome同样携带referer
6.flash打开 中的链接。

7.浏览器未加设置或被用户修改。
有些浏览器可以修改在https网址中是否传递referer信息,但是我没在浏览器中找到这个选项
或者是安装插件referer信息进行屏蔽

最方便可靠的方法还是使用flash,你不能要求所有人都是用最新的浏览器,并且不是右击新窗口打开,或者安装个插件什么的

用flash想到有两种实现方式
1.使用flash按钮替换a标签 然后把链接当作参数传递给flash程序
假如链接是动态的需要计算处理话,可以通过flash调用js函数,然后由这个js函数返回链接地址
2.还有就是js调用flash中的方法
这种最方便了,对原有代码改动最小。
但是弄了几次在chrome总是调用失败,改天在研究下吧

下面是第一种实现方式的示例代码

<!--flash引用代码-->
<object id="open_url" width="25" height="20" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" >
    <param name="movie" value="js/fla_open_url.swf?callback=get_url" />
    <param name="quality" value="high" />
    <param name="wmode" value="transparent" />
    <embed width="25" height="20"  src="js/fla_open_url.swf?callback=get_url" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent"/>
</object>
<script type="text/javascript">
    function get_url(){
        return 'http://www.baidu.com';
    }

</script>

新建个flash,添加个button 在动作中粘贴如下代码

    on (release) { 
        import flash.external.ExternalInterface;
        loadVariablesNum('','callback');//获取js回调函数名称,存放在callback变量中

        if(callback!=''){
            open_url=ExternalInterface.call(callback);//调用js程序,获取url

            if(open_url!=undefined){
                getURL(open_url,'_blank');//在新窗口打开链接 
            }

        }
    }

 notice:

利用ExternalInterface.call调用html里的js函数,参照了flash帮助文档里的做法.可以执行js的函数.但就是无法获取return的值.
网上一大堆教程也只是抄flash帮助文档的东西.也试了allowScriptAccess=always.结果无效,
最后我去搜了N次后,答案居然是只要给<object>加上一个id或是name就解决了.

python argparse模块bug:将版本信息输出到标准错误

今天打算把 kuaipan cli 编译成 二进制版本

kuaipan cli 使用的官方模块argparse解析命令行参数

下面这种方式,已经被官方废弃了,应该是为了解决 -v冲突的问题

parser=argparse.ArgumentParser(version='0.2')

后来修改为

    parser.add_argument('-v','--version', action='version', version='0.2', help="show program's version number and exit")

于是写了个脚本自动编译,并且获取版本号

version=`kuaipan.py -v`
echo $version

但是 $version 始终为空 ,单独执行 kuaipan.py -v是没问题的

运行环境 debian下是Python 2.7.3 ,window下是Python 2.7.6 都不行

然后怀疑是 argparse的问题

查看了下argparse模块的源码 版本号 是 1.1

class _VersionAction(Action):
....
    def __call__(self, parser, namespace, values, option_string=None):
        version = self.version
        if version is None:
            version = parser.version
        formatter = parser._get_formatter()
        formatter.add_text(version)
        parser.exit(message=formatter.format_help())
....
def _print_message(self, message, file=None):
    if message:
        if file is None:
            file = _sys.stderr
        file.write(message)

# ===============
# Exiting methods
# ===============
def exit(self, status=0, message=None):
    if message:
        self._print_message(message, _sys.stderr)
    _sys.exit(status)

问题出来知道了,这里默认的version action 把信息输出到了 stderr标准错误

所以在命令行中获取不到

已经有人提交了issue18920 以及path 不知道什么时候能发布出来

目前临时解决方法是:将标准错误stderr输出到stdout

version=`kuaipan.py -v 2>&1`
echo $version#0.2