第10节,tornado 权限认证,实现完整的登录与登出

1. 前端设计

本文带你使用tornado实现一个完整的网站登录与登出的操作,这个过程涉及到cooke,重定向等技术,需要前端与后端之间进行交互。

前端需要两个页面:

  1. login.html 用户登录页面
  2. welcome.html 用户登录后的欢迎页面

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
        <form action="/login" method="POST">
            Username: <input type="text" name="username" />
            <input type="submit" value="Log In" />
        </form>
    </body>
</html>

welcome.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <h1>Welcome back, </h1>
        <a href="/logout">登出</a>
    </body>
</html>

2. 服务端处理

app.py

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="服务端口号", 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):
        username = self.get_argument("username")
        self.set_secure_cookie("username", username)
        self.redirect("/")


class IndexHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.render('welcome.html', username=self.current_user)

class LogoutHandler(BaseHandler):
    def get(self):
        self.clear_cookie("username")
        self.redirect("/")


def start_app():
    tornado.options.parse_command_line()

    # 设置模板目录
    settings = {
        "template_path": os.path.join(os.path.dirname(__file__), "templates"),
        "cookie_secret": "secret must be hard to guess",
        "login_url": "/login"
    }

    application = tornado.web.Application([
        (r'/', IndexHandler),
        (r'/login', LoginHandler),
        (r'/logout', LogoutHandler)
    ], **settings)

    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()


if __name__ == '__main__':
    start_app()

服务端涉及到了诸多技术,我逐个讲解

2.1 BaseHandler

BaseHandler 是我定义的一个基础类,LoginHandler, IndexHandler 和 LogoutHandler 都继承自这个类,这样设计的好处是可以定义公共的方法。

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        return self.get_secure_cookie("username")

get_current_user 方法tornado.web.RequestHandler 类里的一个方法,BaseHandler类重写了这个方法,这个方法专门用户获取当前用户。

2.2 settings 配置

settings = {
        "template_path": os.path.join(os.path.dirname(__file__), "templates"),
        "cookie_secret": "secret must be hard to guess",
        "login_url": "/login"
    }

这里面的3个配置,一个都不能缺少

  • template_path 配置模板文件的存放目录
  • cookie_secret 配置使用安全cookie的secret
  • login_url 配合tornado.web.authenticated 来使用,如果用户未登录,将自动跳转到login_url 所设置的 url

2.3 tornado.web.authenticated

被tornado.web.authenticated 装饰的方法在调用前会检查current_user,如果这个值为假(None,False, 0, ""), GET请求将会跳转到login_url指定的URL, POST请求将会返回403(Forbidden)。

那些只有登录后才能访问的url,就可以用它来进行控制。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案