tornaod十:XSRF跨站请求伪造
针对跨站请求伪造,通常设置XSRF保护。
XSRF保护:同源策略保护。
XSRF设置:在settings中配置
#config.py # 配置,同django.settings settings = { "xsrf_cookies": True, }
xsrf_cookies设置为True的时侯,开启XSRF保护;False,关闭XSRF保护。
当开启XSRF保护后,所有的访问都将访问不了,包括同源访问。
XSRF保护应用:
1.在模板中应用:在模板中加上 {% module xsrf_form_html() %}
原理、作用:1).为浏览器设置了名为"_xsrf"的安全cookie,这个cookie在关闭浏览器后失效;2).为模板表单添加了一隐藏域,名为_xsrf,值为_xsrf这个cookie的值。
开启模板应用后,同源将可以访问。
添加的隐藏作用域为:
<input type="hidden" name="_xsrf" value="234sfasdf">
2.在非模板中应用
原理同在模板中应用一样,仿照上面用脚本生成一个同样的隐藏作用域。
第一种方式:
1).在模板中应用,会自动设置名为"_xsrf"的cookie。在非模板中应用,需要手动设置名为"_xsrf"的cookie
# 手动设置xsrfCookie (r'/setxsrfcookie', index.SetXSRFCookieHandler),
class SetXSRFCookieHandler(RequestHandler): def get(self, *args, **kwargs): # 这种方式需要自己设置一个value # self.set_secure_cookie("_xsrf", "value") # 第二种方式,会自动设置value,且名为_xsrf的cookie self.xsrf_token self.finish("ok")
2).在模板中,添加脚本,生成一个上面同样的隐藏作用域。
手动创建一个name为"_xsrf",value从浏览器获得的xsrf的value值,的隐藏作用域input。
<form action="/postfile", method="post"> <input type="hidden" id="hi" value=""> <input type="text", name="username"> <hr/> <input type="password", name="pwd"> <hr/> <input type="submit" value="登录"> <script> function getCookie(name) { var ck = document.cookie.match("\\b" + name + "=([^:]*)\\b") return ck ? ck[1] : undefined } document.getElementById("hi").value = getCookie("_xsrf") </script> </form>
访问站点,在浏览器中查看xsrfcookie及其值。
在模板中查看一下xsrfcookie,是否可以获取到,并与浏览器的值比较是否相等。
console.log(getCookie("_xsrf"))
第二种方式:
上面,只是说明了原理。通常,不会使用上面的手动设置的方式;通常,发起ajax请求,点击某个按钮(如login事件),执行某个脚本方法。
使用ajax语法,或者使用jquery。
使用jquery,放在static/js/jquery.min.js。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" charset="utf-8" src="{{ static_url('js/jquery.min.js')}}"></script> </head> <body> <h1>第{{ count }}访问</h1> <input type="hidden" id="hi" value=""> <input type="text", name="username"> <hr/> <input type="password", name="pwd"> <hr/> <input type="submit" value="登录"> <button onclick="login"></button> <script> function getCookie(name) { var ck = document.cookie.match("\\b" + name + "=([^:]*)\\b") return ck ? ck[1] : undefined } function login() { console.log("***查看点击成功") // _xsrf=asdfkj234ka&username=jerry&pwd=234234 // 实际中,用户名和密码用变量代替 $.post("/postfile", "_xsrf="+getCookie('_xsrf') +"&username="+"jerry"+"&pwd="+234234", function(data){ alert("ok") }) } </script> </body> </html>
以上第二种方式:就是在开启XSRF保护后,在发起ajax请求的时侯,带上_xsrf的cookie,并生成第一种方式中产生的同样的隐藏域。
建议使用ajax:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" charset="utf-8" src="{{ static_url('js/jquery.min.js')}}"></script> </head> <body> <h1>第{{ count }}访问</h1> <input type="hidden" id="hi" value=""> <input type="text", name="username"> <hr/> <input type="password", name="pwd"> <hr/> <input type="submit" value="登录"> <button onclick="login"></button> <script> function getCookie(name) { var ck = document.cookie.match("\\b" + name + "=([^:]*)\\b") return ck ? ck[1] : undefined } // _xsrf=asdfkj234ka&username=jerry&pwd=234234 // 实际中,用户名和密码用变量代替 function login() { data = { "username": "jerry", "pwd": "234234" } var dataStr = JSON.stringify(data) // 使用ajax发送一个post请求 $.ajax({ url: "/postfile", method: "POST", data: dataStr, success: function(data){ alert("ok") }, headers: { "X-XSRFToken": getCookie("_xsrf") } }) } </script> </body> </html>
通常,在首页或登录页设置xsrf。
示例:在首页设置xsrf
重新静态加载文件StaticFileHandler的__init__方法,将生成xsrf Cookie加入init;并设置首页路由。最后,使用上面的方法,在模板中或非模板中应用XSRF。
# (r'/(.*)$', tornado.web.StaticFileHandler,
(r'/(.*)$', index.StaticFileHandler,
{"path": os.path.join(config.BASE_DIRS, "static/html"),
"default_filename": "html/index.html"})
class StaticFileHandler(tornado.web.StaticFileHandler): def __init__(self, *args, **kwargs): super(StaticFileHandler, self).__init__(*args, **kwargs) self.xsrf_token
posted on 2018-07-31 21:32 myworldworld 阅读(305) 评论(0) 收藏 举报
浙公网安备 33010602011771号