Tornado with AngularJS

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()就可以获得请求的数据了。