XSRF 处理

最近在学习 AngularJS 中遇到了一个问题,因为 AngularJS 用的是一个单页面,所以所有的访问其实都是走的 AJAX,而一般的 Web 框架都会有 CSRF 保护,如果是使用 jQuery 来发送 Ajax 请求,在官方文档有给出例子。但是我现在用的 AngularJS,在我的 templates 里只有一个 index.html 文件,所有的页面都是 AngularJS 的ngView

在官方给出的 jQuery 例子中,是利用的 Cookie 中存的_xsrf附加在 AJAX 的参数中,那么问题来了,这个_xsrf的要首先响应到浏览器中,在 Tornado 中,如果通过常规表单 POST 的话,必须在form里加上{% module xsrf_form_html() %}来生成一个_xsrf的值,通过追踪xsrf_form_html这个函数,设置_xsrf是手动的,如果仅有一个index.html文件,那么就没法显示的设置_xsrf

下面是我的解决方法

class BaseHandler(tornado.web.RequestHandler):

    def on_finish(self):
        self.set_cookie("_xsrf", self.xsrf_token)

这里设置好了_xsrf,在 AngularJS 中有提供自动处理 XSRF 的方法参考

app.config(function($httpProvider) {
    $httpProvider.defaults.xsrfCookieName = "_xsrf";
    $httpProvider.defaults.xsrfHeaderName = "X-XSRFToken";
});

POST 参数处理

还有一个问题,在 AngularJS 中,POST 传递的是 application/json 格式的数据参考,所以在 Tornado 中接收到的参数是在 body 中,所以通过RequestHandler.get_arguments()是获取不到的,所以重新处理一下接收到的数据

class BaseHandler(BaseHandler):

    def prepare(self):

        args = dict()
        if self.request.body:
            try:
                args = helpers.json_loads(self.request.body)
            except ValueError:
                pass

        self.args = args

接下来在RequestHandler里使用RequestHandler.args.get()就可以获得请求的数据了。