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

2018-02-24 15:48 更新

上一節(jié)中已經(jīng)對(duì)安全問(wèn)題進(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ù)庫(kù)驗(yàn)證。這不僅是直接的,也是基本的流程。但是,這個(gè)過(guò)程如果總讓用戶自己來(lái)做,框架的作用就顯不出來(lái)了。tornado就提供了一種用戶驗(yàn)證方法。

為了后面更工程化地使用tornado編程。需要將前面的已經(jīng)有的代碼進(jìn)行重新梳理。我只是將有修改的文件代碼寫出來(lái),不做過(guò)多解釋,必要的有注釋,相信讀者在前述學(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。在這里特別要向讀者說(shuō)明,在這個(gè)類中,其實(shí)還可以寫不少別的東西,比如你就可以將數(shù)據(jù)庫(kù)連接寫到這個(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,方法見(jiàn)下面
                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è)專門用來(lái)顯示錯(cuò)誤的頁(yè)面
    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中把它讀出來(lái),使用user的值時(shí),還會(huì)用到:

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

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

接下來(lái)要對(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)前合法用戶。在原來(lái)的代碼中,用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ù)庫(kù)查詢。

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ì)返回到首頁(yè)。當(dāng)然,如果有單獨(dú)的登錄界面,比如是/login,也可以login_url = '/login'

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

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

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)