Torando源码解析之XSRF防护的实现

Torando源码解析之XSRF防护的实现Torando源码解析之XSRF防护的实现Torando源码解析之XSRF防护的实现Tornado开启XSRF防护的方法源码解析xsrf_form_html()是什么self.xsrf_token是什么Tornado开启XSRF防护的方法http://tornado-zh.readthedocs.io/zh/latest/guide/security.ht…

大家好,又见面了,我是你们的朋友全栈君。

Torando源码解析之XSRF防护的实现

Tornado开启XSRF防护的方法

http://tornado-zh.readthedocs.io/zh/latest/guide/security.html

核心代码如下
Tornado开启xsrf_cookies

settings = {
    "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
    "login_url": "/login",
    "xsrf_cookies": True,
}
application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/login", LoginHandler),
], **settings)

HTML页面添加相关的代码

<form action="/new_message" method="post"> {% module xsrf_form_html() %} ...... </form>

源码解析

在上述的代码中,很明显可以看出,所谓开启xsrf防护,其实就是在post提交的数据里面带上 {% module xsrf_form_html() %} 这段代码所包含的东西

xsrf_form_html()是什么

找到tornado的目录,然后再该目录下通过linux命令找到xsrf_form_html

grep xsrf_form_html -r *

查看grep结果,找到相关代码如下

def xsrf_form_html(self):
    return '<input type="hidden" name="_xsrf" value="' + \
        escape.xhtml_escape(self.xsrf_token) + '"/>'

发现所谓的 {% module xsrf_form_html() %}其实就是隐藏的一个

self.xsrf_token是什么

同样的方法找到xsrf_token

@property
def xsrf_token(self):
    if not hasattr(self, "_xsrf_token"):
        version, token, timestamp = self._get_raw_xsrf_token()
        output_version = self.settings.get("xsrf_cookie_version", 2)
        cookie_kwargs = self.settings.get("xsrf_cookie_kwargs", {})
        if output_version == 1:
            self._xsrf_token = binascii.b2a_hex(token)
        elif output_version == 2:
            mask = os.urandom(4)
            self._xsrf_token = b"|".join([
                b"2",
                binascii.b2a_hex(mask),
                binascii.b2a_hex(_websocket_mask(mask, token)),
                utf8(str(int(timestamp)))])
        else:
            raise ValueError("unknown xsrf cookie version %d",
                             output_version)
        if version is None:
            expires_days = 30 if self.current_user else None
            self.set_cookie("_xsrf", self._xsrf_token,
                            expires_days=expires_days,
                            **cookie_kwargs)
    return self._xsrf_token

其中,@property 是将该类函数设置成属性访问的装饰器
像第一次访问的时候,_xsrf_token这个值肯定是没有的
由代码可以看出token是其实就是self.xsrf_token的关键

def _get_raw_xsrf_token(self):
    if not hasattr(self, '_raw_xsrf_token'):
        cookie = self.get_cookie("_xsrf")
        if cookie:
            version, token, timestamp = self._decode_xsrf_token(cookie)
        else:
            version, token, timestamp = None, None, None
        if token is None:
            version = None
            token = os.urandom(16)
            timestamp = time.time()
        self._raw_xsrf_token = (version, token, timestamp)
    return self._raw_xsrf_token

这里其实就很明显可以看出
如果是第一次生成token,那么

token = os.urandom(16)

os.urandom(n) 是随机生成n个字节的函数
所以,token就是一个随机的16字节的串

如果不是第一次。那么会从cookie里面去获取token,并将这个token重新传回给前端

def _decode_xsrf_token(self, cookie):
    try:
        m = _signed_value_version_re.match(utf8(cookie))


        if m:
            version = int(m.group(1))
            if version == 2:
                _, mask, masked_token, timestamp = cookie.split("|")


                mask = binascii.a2b_hex(utf8(mask))
                token = _websocket_mask(
                    mask, binascii.a2b_hex(utf8(masked_token)))
                timestamp = int(timestamp)
                return version, token, timestamp
            else:
                raise Exception("Unknown xsrf cookie version")
        else:
            version = 1
            try:
                token = binascii.a2b_hex(utf8(cookie))
            except (binascii.Error, TypeError):
                token = utf8(cookie)           
            timestamp = int(time.time())
            return (version, token, timestamp)
    except Exception:
        gen_log.debug("Uncaught exception in _decode_xsrf_token",
                      exc_info=True)
        return None, None, None

这个与前面的xsrf_token 函数相对应,因为在传给前端的时候token进行了”encode”,所以获取的时候需要“decode”下。
当然这里所谓的”encode”和”decode”,其实仅仅是将版本号和当前的时间戳以某种规则加在了返回的token两边。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/144705.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • js中array_javascript array

    js中array_javascript array为什么80%的码农都做不了架构师?>>>…

  • 轻量级神经网络发展_宽度神经网络

    轻量级神经网络发展_宽度神经网络文章目录轻量级神经网络——shuffleNetshuffleNet1逐点分组卷积(Pointwisegroupconvolution)✨✨✨通道重排(channelshuffle)✨✨✨shuffleNetUnit✨✨✨shuffleNet1的网络结果和效果轻量级神经网络——shuffleNetshuffleNet1  在之前,已经讨论过一种轻量级神经网络——MobileNet,文中对MobileNet的三个版本都做了详细的介绍,读此篇之前,建议先了解MobileNet,特别是要对其中的深度可

  • 飞猪双11挑战_天猫双十一晚会极限挑战

    飞猪双11挑战_天猫双十一晚会极限挑战摘要: EagleEye作为阿里集团老牌的链路跟踪系统,其自身业务虽不在交易链路上,但却监控着全集团的链路状态,特别是在中间件的远程调用上,覆盖了集团绝大部分的场景,在问题排查和定位上发挥着巨大的作用,保障了各个系统的稳定性,为整个技术团队打赢这场战役保驾护航。作者:王华锋(水彧)背景双十一一直是阿里巴巴集团每年要打的一场大战役。要打赢这场战役,技术上,不仅仅是几个应用

  • Python学习笔记三(开发进阶)

    Python学习笔记三(开发进阶)本文主要针对python的package、面向对象编程等进行详述。

  • httprunner(6)配置信息config

    httprunner(6)配置信息config前言每个测试用例都应该有config部分,可以配置用例级别。比如name、base_url、variables、verify、export等等案例演示fromhttprunnerimport

  • iOS多用连接、反向协议、安全

    iOS多用连接、反向协议、安全

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号