Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tornado专题 #14

Open
ferstar opened this issue Jan 3, 2020 · 1 comment
Open

Tornado专题 #14

ferstar opened this issue Jan 3, 2020 · 1 comment
Labels

Comments

@ferstar
Copy link
Owner

@ferstar ferstar commented Jan 3, 2020

@ferstar ferstar changed the title Tornado断点续传 Tornado专题 Jan 7, 2020
@ferstar

This comment has been minimized.

Copy link
Owner Author

@ferstar ferstar commented Jan 7, 2020

2. CSRF

维基传送门,这里只说说咋防

其实tornado已经有对应的实现
大概就是每次请求多带一个预先分发的token,然后用浏览器cookie里的token跟这个做比对

但实际实施过程中总有些接口比如/login,都没登录自然拿不到派发的_xsrf,所以这个接口不能开csrf验证,再比如我们各个微服务间的通讯一般是用基于token的认证方式,这种方式是免疫csrf的,自然也不需要验证,基于可能的自定义需求,我们需要重写这个方法check_xsrf_cookie

# 你肯定得有个类似`BaseHandler`的类
class BaseHandler(tornado.web.RequestHandler):
    def __init__(self, *args, **kwargs):
        """此处省略若干自定义初始化过程"""
        pass

    def check_xsrf_cookie(self):
        if not get_config('xsrf开关', False):
            return None
        for route_ext in get_config('不检查的路由白名单', []):
            if re.search(rf'不检查的路由', self.request.path):
                logging.debug('Skip xsrf check: %s', self.request.path)
                return None
        # 可能有些系统内接口用的是token认证,那么这些接口也是不需要检查xsrf的,所以也要跳过
        url = self.request.full_url()
        query = urllib.parse.urlparse(url).query
        params = urllib.parse.parse_qs(query) if query else {}
        if all([v for k, v in params.items() if k in ('藏在url里的token key1', '藏在url里的token key2')] or [None]):
            logging.debug('Skip xsrf check: %s', self.request.path)
            return None
        try:
            super(BaseHandler, self).check_xsrf_cookie()
        except tornado.web.HTTPError as exp:
            # 返回一个对前端友好的错误消息提示
            return custom_error(self, exp.status_code, str(exp))
        return None
...

# 你的Application类需要塞进去点参数
class Application(tornado.web.Application):

    def __init__(self):
        ...

        settings = {
            'compiled_template_cache': False,
            'template_path': 'templates',
            'serve_traceback': get_config('要不要开调试', True),
            'xsrf_cookies': get_config('要不要开xsrf验证', False),
            'xsrf_cookie_kwargs': dict(httponly=True),  # _xsrf cookie 加个`httponly`的属性,这样脚本就没办法偷你的cookie了
            "cookie_secret": "a_u_ok?",
        }
        tornado.web.Application.__init__(self, handlers, debug=get_config("要不要开调试", True), **settings)
...

接下来告诉前端同学,任何POSTDELETEPUT请求都带上_xsrf参数或者X-Xsrftoken请求头或者X-Csrftoken请求头,不要问为什么,问就甩源码

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.