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两边。

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • oracle的todate函数的日期格式_oracle date格式

    oracle的todate函数的日期格式_oracle date格式转自http://apps.hi.baidu.com/share/detail/10070907OracleTO_DATE日期格式大全Oracle中TO_DATE格式2009-04-1410:53TO_DATE格式(以时间:2007-11-02  13:45:25为例)       Year:            yytwodigits两位年              …

    2022年10月12日
    4
  • c#attribute应用_sql float

    c#attribute应用_sql float今天研究了一下C#中的Attributes的用法,感觉很有用,现总结以下:    在前台用JS写的脚本方法,除了可以直接用在前台控件的属性中,还可以在后台运用。      即在后台页面加载时,调用JS方法。语法格式有两种,如下:      第一种写法:控件ID名.Attributes.Add(“事件名称”,“JS方法”);      如:一个按钮控件Butto

    2022年9月25日
    2
  • 详解布隆过滤器的原理、优缺点

    详解布隆过滤器的原理、优缺点什么是布隆过滤器?本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilisticdatastructure),特点是高效地插入和查询,可以用来告诉你“某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。HashMap的问题讲述布隆过滤器的原理之前,我们先思考一下,通常你判断某…

    2022年9月1日
    8
  • calico文件_ico文件怎么打开

    calico文件_ico文件怎么打开k8s的网络插件,可以使用下面的,镜像可以自己修改。

    2025年7月2日
    3
  • LQR控制器(控制器的功能是什么)

    LQR控制器是常见的最优控制器,它的主要特点是将控制量加入到了成本函数中。对于线性系统:x˙=Ax+Bu\dotx=Ax+Bux˙=Ax+Bu设计控制器u=−Kxu=-Kxu=−Kx使得J=12∫0∞xTQx+uTRu dtJ=\frac{1}{2}\int_0^\inftyx^TQx+u^TRu\,dtJ=21​∫0∞​xTQx+uTRudt最小。其中,xTQxx^TQxxTQx是状态部分,uTRuu^TRuuTRu是控制部分。为了求解K,需要引入Riccati微分方程:P

    2022年4月18日
    194
  • mysql左连接和右连接_MYSQL 左连接与右连接

    mysql左连接和右连接_MYSQL 左连接与右连接一、LEFTJOINLEFTJOIN关键字从左表(table1)返回所有的行,即使右表(table2)中没有匹配。如果右表中没有匹配,则结果为NULL。语法:SELECTcolumn_name(s)FROMtable1LEFTJOINtable2ONtable1.column_name=table2.column_name;举例:下面是选自”Websites”表的数据:下面…

    2022年6月4日
    33

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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