Tornado入门(七):用户认证、cookie、xsrf
一、header:
设置header:self.set_header("name", "value")
设置默认header:self.set_default_header()
获取header:self.request.headers
二、Cookies和安全Cookies
设置cookie:self.set_cookie("mycookie", "myvalue")
获取cookie:self.get_cookie("mycookie")
设置安全cookie:self.set_secure_cookie("mycookie", "myvalue")
获取安全cookie:self.get_secure_cookie("mycookie")
设置、获取浏览器中的cookies信息:
class MainHandler(tornado.web.RequestHandler): def get(self): if not self.get_cookie("mycookie"): self.set_cookie("mycookie", "myvalue") self.write("Your cookie was not set yet!") else: self.write("Your cookie was set!")
Cookies信息通常不安全,很容易被篡改。
如果需要通过cookies来区分不同的登录用户,则需要对cookies进行签名,以防伪造。
Tornado通过set_secure_cookie和get_secure_cookie方法支持签名Cookies。
为了使用这两个方法,需要在应用中配置cookie_secret。
application = tornado.web.Application([ (r"/", MainHandler), ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
签过名的cookies包含了编码之后的cookie值,时间戳,和一个HMAC签名。
如果cookie过期或者签名不匹配,则get_secure_cookie将返回None。
class MainHandler(tornado.web.RequestHandler): def get(self): if not self.get_secure_cookie("mycookie"): self.set_secure_cookie("mycookie", "myvalue") self.write("Your cookie was not set yet!") else: self.write("Your cookie was set!")
Tornado的安全cookie机制并不能保证绝对的安全,一是因为cookie值可以被用户看到,二是因为cookie_secret是一个对称密钥,所以必须确保它的安全。
默认情况下,Tornado cookies的生存期为30天,如果需要修改,可以将参数expire_days传递给set_secure_cookie 和 max_age_days参数传递给get_secure_cookie。这个两个参数是分别传递的。
三、用户认证:self.current_user,
认证过的用户可以通过self.current_user访问,在模板中可以通过current_user访问,默认情况下current_user为None。
为了实现用户认证,需要重写处理器中的get_current_user方法,以确定当前的用户。下面是一个简单的示例。
class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("user") class MainHandler(BaseHandler): def get(self): if not self.current_user: self.redirect("/login") return name = tornado.escape.xhtml_escape(self.current_user) self.write("Hello, " + name) class LoginHandler(BaseHandler): def get(self): self.write('<html><body><form action="/login" method="post">' 'Name: <input type="text" name="name">' '<input type="submit" value="Sign in">' '</form></body></html>') def post(self): self.set_secure_cookie("user", self.get_argument("name")) self.redirect("/") application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
用户认证装饰器:
通过tornado.web.authenticated修饰器来进行用户认证,只有用户登录过之后,才可以访问当前请求,否则重定向至login_url(在应用中进行配置)。
class MainHandler(BaseHandler): @tornado.web.authenticated def get(self): name = tornado.escape.xhtml_escape(self.current_user) self.write("Hello, " + name) settings = { "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login", } application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), ], **settings)
第三方认证
tornado.auth模块实现了第三方的认证协议,包括Google和Facebook等。
下面是使用Google的认证:
class GoogleOAuth2LoginHandler(tornado.web.RequestHandler, tornado.auth.GoogleOAuth2Mixin): @tornado.gen.coroutine def get(self): if self.get_argument('code', False): user = yield self.get_authenticated_user( redirect_uri='http://your.site.com/auth/google', code=self.get_argument('code')) # Save the user with e.g. set_secure_cookie else: yield self.authorize_redirect( redirect_uri='http://your.site.com/auth/google', client_id=self.settings['google_oauth']['key'], scope=['profile', 'email'], response_type='code', extra_params={'approval_prompt': 'auto'})
四、跨站请求伪造
跨站请求伪造是很多个人网站都会遇到的安全问题。
通常防止XSRF的方法是传递一个不可预测的cookie值给用户,然后用户提交表单时携带这个值。如果cookie信息-和表中的值不匹配,则说明请求时可能是伪造的。
Tornado内置了XSRF防御机制,通过在应用中设置xsrf_cookies参数来开启。
settings = { "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login", "xsrf_cookies": True, } application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), ], **settings)
如果配置了xsrf_cookies, 则Tornado应用会为所有的用户设置_xsrfcookie,并拒绝所有没有携带正确的_xsrf字段的POST,PUT或者DELETE请求。注意需要确保所有提交的表单都包含了这个字段。可以使用UIModule xsrf_form_html()。
<form action="/new_message" method="post"> {% module xsrf_form_html() %} <input type="text" name="message"/> <input type="submit" value="Post"/> </form>
如果是通过Ajax提交表单,同样需要确保提供了_xsrf字段 :
function getCookie(name) { var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); return r ? r[1] : undefined; } jQuery.postJSON = function(url, args, callback) { args._xsrf = getCookie("_xsrf"); $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST", success: function(response) { callback(eval("(" + response + ")")); }}); };
对于PUT和DELETE, xsrf_form_html可以通过头部字段X-XSRFToken设置。
如果需要自定义XSRF的行为,可以重写RequestHandler.check_xsrf_cookie方法。
参考:https://www.jianshu.com/p/d5c562045618
posted on 2018-01-22 17:45 myworldworld 阅读(286) 评论(0) 收藏 举报
浙公网安备 33010602011771号