在在搞Django 1.3和Uploadify的整合时,被莫名其妙的302困扰,在苦思之后突然发现,原来Uploadify发送请求时是不会发送Cookie信息的。火急火燎地弄了个middleware来将POST中对应字段写到request.COOKIES去。这样一搞,302倒是ok了,但403倒跑了出来。使用抽插,哦不,抽查法找到是Csrf的验证问题,于是天真地把csrfmiddlewaretoken塞到POST里,可是403依旧。甚是火大。
只好乖乖地看源码,看看Django是如何做CSRF验证的。Django是在CsrfViewMiddleware中进行的相关验证,验证过程很简单,从Cookie中拿出token,然后从POST中拿出csrfmiddlewaretoken,然后块俩做一个字符匹配,就哦了。于是明白了,不就再传个cookie嘛,但突然一想,不对呀,csrfmiddlewaretoken的值就是从cookie里拿的,再传同一个值来做验证,这不是和没验证没啥区别么……
于是做了一个试验,结果确实如此,这下Django悲剧了……
实验项目可以在这个地址下载,运行runserver后,用curl来验证
直接GET,无障碍
curl http://127.0.0.1:8000
强制GET,无障碍
curl -G -d test=test http://127.0.0.1:8000
POST,403了,ms没问题?
curl -d test=test http://127.0.0.1:8000
POST,随便加上csrf,靠!!居然过了!!!
curl -d "test=test;csrfmiddlewaretoken=1" -b csrftoken=1 http://127.0.0.1:8000
归根结底,还是这个验证方法有问题,起码post中的token和cookie中的token是用secret_key做过变幻的,这样才能避免伪造,否则,神马都是浮云~~ 望天
P.S. 报bug去了,#15845。不知他们会采用我说的方法不⋯⋯
Updated: 呃,一般情况下大约是不会有问题的,因为这只是可以任意伪造csrf_token,但通常还有需要csrf保护的地方也会需要sessionid来作用户验证。这篇的问题就可以暂时忽略了。

