鍍金池/ 教程/ Python/ 用 tornado 做網(wǎng)站 (6)
標(biāo)準(zhǔn)庫 (4)
如何成為 Python 高手
標(biāo)準(zhǔn)庫 (6)
標(biāo)準(zhǔn)庫 (3)
類(2)
Pandas 使用 (2)
xml
用 tornado 做網(wǎng)站 (5)
文件(1)
練習(xí)
列表(3)
從小工到專家
除法
錯(cuò)誤和異常 (2)
函數(shù)(1)
用 tornado 做網(wǎng)站 (7)
為做網(wǎng)站而準(zhǔn)備
函數(shù)練習(xí)
標(biāo)準(zhǔn)庫 (8)
Pandas 使用 (1)
回顧 list 和 str
字典(1)
用 tornado 做網(wǎng)站 (3)
字符串(1)
函數(shù)(2)
寫一個(gè)簡單的程序
將數(shù)據(jù)存入文件
語句(5)
SQLite 數(shù)據(jù)庫
集成開發(fā)環(huán)境(IDE)
集合(1)
類(1)
用 tornado 做網(wǎng)站 (6)
用 tornado 做網(wǎng)站 (2)
自省
語句(4)
錯(cuò)誤和異常 (1)
用 tornado 做網(wǎng)站 (4)
集合(2)
列表(1)
標(biāo)準(zhǔn)庫 (1)
生成器
mysql 數(shù)據(jù)庫 (1)
第三方庫
實(shí)戰(zhàn)
運(yùn)算符
類(3)
字典(2)
語句(1)
數(shù)和四則運(yùn)算
語句(2)
文件(2)
MySQL 數(shù)據(jù)庫 (2)
電子表格
迭代器
mongodb 數(shù)據(jù)庫 (1)
特殊方法 (2)
特殊方法 (1)
字符編碼
編寫模塊
用 tornado 做網(wǎng)站 (1)
標(biāo)準(zhǔn)庫 (5)
函數(shù)(4)
類(5)
字符串(2)
關(guān)于 Python 的故事
函數(shù)(3)
字符串(4)
處理股票數(shù)據(jù)
常用數(shù)學(xué)函數(shù)和運(yùn)算優(yōu)先級(jí)
字符串(3)
為計(jì)算做準(zhǔn)備
多態(tài)和封裝
類(4)
迭代
語句(3)
錯(cuò)誤和異常 (3)
分析 Hello
Python 安裝
標(biāo)準(zhǔn)庫 (2)
列表(2)
元組

用 tornado 做網(wǎng)站 (6)

上一節(jié)中已經(jīng)對(duì)安全問題進(jìn)行了描述,另外一個(gè)內(nèi)容是不能忽略的,那就是用戶登錄之后,對(duì)當(dāng)前用戶狀態(tài)(用戶是否登錄)進(jìn)行判斷。

用戶驗(yàn)證

用戶登錄之后,當(dāng)翻到別的目錄中時(shí),往往需要驗(yàn)證用戶是否處于登錄狀態(tài)。當(dāng)然,一種比較直接的方法,就是在轉(zhuǎn)到每個(gè)目錄時(shí),都從 cookie 中把用戶信息,然后傳到后端,跟數(shù)據(jù)庫驗(yàn)證。這不僅是直接的,也是基本的流程。但是,這個(gè)過程如果總讓用戶自己來做,框架的作用就顯不出來了。tornado 就提供了一種用戶驗(yàn)證方法。

為了后面更工程化地使用 tornado 編程。需要將前面的已經(jīng)有的代碼進(jìn)行重新梳理。我只是將有修改的文件代碼寫出來,不做過多解釋,必要的有注釋,相信讀者在前述學(xué)習(xí)基礎(chǔ)上,能夠理解。

在 handler 目錄中增加一個(gè)文件,名稱是 base.py,代碼如下:

#! /usr/bin/env python
# coding=utf-8

import tornado.web

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

在這個(gè)文件中,目前只做一個(gè)事情,就是建立一個(gè)名為 BaseHandler 的類,然后在里面放置一個(gè)方法,就是得到當(dāng)前的 cookie。在這里特別要向讀者說明,在這個(gè)類中,其實(shí)還可以寫不少別的東西,比如你就可以將數(shù)據(jù)庫連接寫到這個(gè)類的初始化__init__()方法中。因?yàn)樵谄渌念愔?,我們要繼承這個(gè)類。所以,這樣一個(gè)架勢(shì),就為讀者以后的擴(kuò)展增加了冗余空間。

然后把 index.py 文件改寫為:

#!/usr/bin/env Python
# coding=utf-8

import tornado.escape
import methods.readdb as mrd
from base import BaseHandler

class IndexHandler(BaseHandler):    #繼承 base.py 中的類 BaseHandler
    def get(self):
    usernames = mrd.select_columns(table="users",column="username")
    one_user = usernames[0][0]
    self.render("index.html", user=one_user)

    def post(self):
        username = self.get_argument("username")
        password = self.get_argument("password")
        user_infos = mrd.select_table(table="users",column="*",condition="username",value=username)
        if user_infos:
            db_pwd = user_infos[0][2]
            if db_pwd == password:
                self.set_current_user(username)    #將當(dāng)前用戶名寫入 cookie,方法見下面
                self.write(username)
            else:
                self.write("-1")
        else:
            self.write("-1")

    def set_current_user(self, user):
        if user:
            self.set_secure_cookie('user', tornado.escape.json_encode(user))    #注意這里使用了 tornado.escape.json_encode() 方法
        else:
            self.clear_cookie("user")

class ErrorHandler(BaseHandler):    #增加了一個(gè)專門用來顯示錯(cuò)誤的頁面
    def get(self):                                        #但是后面不單獨(dú)講述,讀者可以從源碼中理解
        self.render("error.html")

在 index.py 的類 IndexHandler 中,繼承了 BaseHandler 類,并且增加了一個(gè)方法 set_current_user() 用于將用戶名寫入 cookie。請(qǐng)讀者特別注意那個(gè) tornado.escape.json_encode() 方法,其功能是:

tornado.escape.json_encode(value) JSON-encodes the given Python object.

如果要查看源碼,可以閱讀:http://www.tornadoweb.org/en/branch2.3/escape.html

這樣做的本質(zhì)是把 user 轉(zhuǎn)化為 json,寫入到了 cookie 中。如果從 cookie 中把它讀出來,使用 user 的值時(shí),還會(huì)用到:

tornado.escape.json_decode(value) Returns Python objects for the given JSON string

它們與json 模塊中的 dump()、load()功能相仿。

接下來要對(duì) user.py 文件也進(jìn)行重寫:

#!/usr/bin/env Python
# coding=utf-8

import tornado.web
import tornado.escape
import methods.readdb as mrd
from base import BaseHandler

class UserHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        #username = self.get_argument("user")
        username = tornado.escape.json_decode(self.current_user)
        user_infos = mrd.select_table(table="users",column="*",condition="username",value=username)
        self.render("user.html", users = user_infos)

在 get() 方法前面添加 @tornado.web.authenticated,這是一個(gè)裝飾器,它的作用就是完成 tornado 的認(rèn)證功能,即能夠得到當(dāng)前合法用戶。在原來的代碼中,用 username = self.get_argument("user") 方法,從 url 中得到當(dāng)前用戶名,現(xiàn)在把它注釋掉,改用 self.current_user,這是和前面的裝飾器配合使用的,如果它的值為假,就根據(jù) setting 中的設(shè)置,尋找 login_url 所指定的目錄(請(qǐng)關(guān)注下面對(duì) setting 的配置)。

由于在 index.py 文件的 set_current_user() 方法中,是將 user 值轉(zhuǎn)化為 json 寫入 cookie 的,這里就得用 username = tornado.escape.json_decode(self.current_user) 解碼。得到的 username 值,可以被用于后一句中的數(shù)據(jù)庫查詢。

application.py 中的 setting 也要做相應(yīng)修改:

#!/usr/bin/env Python
# coding=utf-8

from url import url

import tornado.web
import os

setting = dict(
    template_path = os.path.join(os.path.dirname(__file__), "templates"),
    static_path = os.path.join(os.path.dirname(__file__), "statics"),
    cookie_secret = "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E=",
    xsrf_cookies = True,
    login_url = '/',
)

application = tornado.web.Application(
    handlers = url,
    **setting
)

與以前代碼的重要區(qū)別在于 login_url = '/',,如果用戶不合法,根據(jù)這個(gè)設(shè)置,會(huì)返回到首頁。當(dāng)然,如果有單獨(dú)的登錄界面,比如是 /login,也可以 login_url = '/login'

如此完成的是用戶登錄到網(wǎng)站之后,在頁面轉(zhuǎn)換的時(shí)候?qū)崿F(xiàn)用戶認(rèn)證。

為了演示本節(jié)的效果,我對(duì)教程的源碼進(jìn)行修改。讀者在閱讀的時(shí)候,可以參照源碼。


總目錄   |   上節(jié):用 tornado 做網(wǎng)站 (5)   |   下節(jié):用 tornado 做網(wǎng)站 (7)

如果你認(rèn)為有必要打賞我,請(qǐng)通過支付寶:qiwsir@126.com,不勝感激。