在本节中,咱们将创建一个应用,询问访客的名字,而后将其存储在安全cookie中,以便以后取出。后续的请求将认出回客,并展现给她一个定制的页面。你将学到login_url参数和tornado.web.authenticated装饰器的相关知识,这将消除在相似应用中常常会涉及到的一些头疼的问题。html
在这个例子中,咱们将只经过存储在安全cookie里的用户名标识一我的。当某人首次在某个浏览器(或cookie过时后)访问咱们的页面时,咱们展现一个登陆表单页面。表单做为到LoginHandler路由的POST请求被提交。post方法的主体调用set_secure_cookie()来存储username请求参数中提交的值。python
代码清单6-2中的Tornado应用展现了咱们本节要讨论的验证函数。LoginHandler类渲染登陆表单并设置cookie,而LogoutHandler类删除cookie。web
import tornado.httpserver import tornado.ioloop import tornado.web import tornado.options import os.path from tornado.options import define, options define("port", default=8000, help="run on the given port", type=int) class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("username") class LoginHandler(BaseHandler): def get(self): self.render('login.html') def post(self): self.set_secure_cookie("username", self.get_argument("username")) self.redirect("/") class WelcomeHandler(BaseHandler): @tornado.web.authenticated def get(self): self.render('index.html', user=self.current_user) class LogoutHandler(BaseHandler): def get(self): if (self.get_argument("logout", None)): self.clear_cookie("username") self.redirect("/") if __name__ == "__main__": tornado.options.parse_command_line() settings = { "template_path": os.path.join(os.path.dirname(__file__), "templates"), "cookie_secret": "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E=", "xsrf_cookies": True, "login_url": "/login" } application = tornado.web.Application([ (r'/', WelcomeHandler), (r'/login', LoginHandler), (r'/logout', LogoutHandler) ], **settings) http_server = tornado.httpserver.HTTPServer(application) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
代码清单6-3和6-4是应用templates/目录下的文件。数据库
<html> <head> <title>Please Log In</title> </head> <body> <form action="/login" method="POST"> {% raw xsrf_form_html() %} Username: <input type="text" name="username" /> <input type="submit" value="Log In" /> </form> </body> </html>
<html> <head> <title>Welcome Back!</title> </head> <body> <h1>Welcome back, {{ user }}</h1> </body> </html>
为了使用Tornado的认证功能,咱们须要对登陆用户标记具体的处理函数。咱们可使用@tornado.web.authenticated装饰器完成它。当咱们使用这个装饰器包裹一个处理方法时,Tornado将确保这个方法的主体只有在合法的用户被发现时才会调用。让咱们看看例子中的WelcomeHandler吧,这个类只对已登陆用户渲染index.html模板。浏览器
class WelcomeHandler(BaseHandler): @tornado.web.authenticated def get(self): self.render('index.html', user=self.current_user)
在get方法被调用以前,authenticated装饰器确保current_usr属性有值。(咱们将简短的讨论这个属性。)若是current_user值为假(None、False、0、""),任何GET或HEAD请求都将把访客重定向到应用设置中login_url指定的URL。此外,非法用户的POST请求将返回一个带有403(Forbidden)状态的HTTP响应。安全
若是发现了一个合法的用户,Tornado将如期调用处理方法。为了实现完整功能,authenticated装饰器依赖于current_user属性和login_url设置,咱们将在下面看到具体讲解。cookie
请求处理类有一个current_user属性(一样也在处理程序渲染的任何模板中可用)能够用来存储为当前请求进行用户验证的标识。其默认值为None。为了authenticated装饰器可以成功标识一个已认证用户,你必须覆写请求处理程序中默认的get_current_user()方法来返回当前用户。app
实际的实现由你决定,不过在这个例子中,咱们只是从安全cookie中取出访客的姓名。很明显,你但愿使用一个更加鲁棒的技术,可是出于演示的目的,咱们将使用下面的方法:函数
class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("username")
尽管这里讨论的例子并无在存储和取出用户密码或其余凭证上有所深刻,但本章中讨论的技术能够以最小的额外努力来扩展到查询数据库中的认证。tornado
让咱们简单看看应用的构造函数。记住这里咱们传递了一个新的设置给应用:login_url是应用登陆表单的地址。若是get_current_user方法返回了一个假值,带有authenticated装饰器的处理程序将重定向浏览器的URL以便登陆。
settings = { "template_path": os.path.join(os.path.dirname(__file__), "templates"), "cookie_secret": "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E=", "xsrf_cookies": True, "login_url": "/login" } application = tornado.web.Application([ (r'/', WelcomeHandler), (r'/login', LoginHandler), (r'/logout', LogoutHandler) ], **settings)
当Tornado构建重定向URL时,它还会给查询字符串添加一个next参数,其中包含了发起重定向到登陆页面的URL资源地址。你可使用像self.redirect(self.get_argument('next', '/'))这样的行来重定向登陆后用户回到的页面。