1.登錄檢查(裝飾器的使用)
我們登錄的時候需要驗證,但是如果有很多地方需要驗證,這個時候就會出現很多重復代碼的情況,這個時候我們需要一個不改變函數運行,又能給函數加上驗證過程方法,很明顯,我們可以使用裝飾器來達到這個功能,代碼如下:
def auth(fun): def wrapper(self,*args,**kwargs): id = self.get_secure_cookie('ID') if id: return fun(self,*args,**kwargs) else: self.redirect('/login') return wrapper
#定義好裝飾器之后,就可以直接去修飾需要驗證的方法
class IndexHandler(BaseHandler): @auth def get(self): self.write('登錄成功---index')
使用裝飾器可以很方便我們去做登錄檢查,可以節省出大量的代碼,增加程序的可讀性和程序整體的美觀。
2.authenticated
雖然我們自己可以做這個登錄檢查,但是在tornado內部給我們提供了一個內置的裝飾器`authenticated`這個可以幫我們自動的進行登錄驗證,`authenticated`可以省去我們自己重復造輪子的過程,但是在使用的時候需要注意幾點:
# Application中添加配置 login_url='/login', # 重寫 get_current_user 方法 class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): current_user = self.get_secure_cookie('ID') if current_user: return current_user return None # 裝飾需要驗證的方法 @authenticated
有些時候我們需要跳轉到之前的頁面怎么做呢?當我們使用`authenticated`的時候我們可以十分方便的做這件事情。我們觀察跳轉之后的url就可以發現,如果是使用`authenticated`裝飾器裝飾之后,而跳轉到登錄頁面之后,在登錄頁面的url中,可以看到最后面會添加上一個next參數,這個就是我們剛才跳轉的路由,通過這個參數,我們就可以很方便的跳轉回之前的的路由,具體實現如下:
class LoginHandler(BaseHandler): def get(self): nextname = self.get_argument('next','') self.render('authenticated.html',nextname=nextname) def post(self): nextname = self.get_argument('next', '') username = self.get_argument('name','') username = User.by_name(username) passwd = self.get_argument('password', '') print(username) if username and username[0].password == passwd: self.set_secure_cookie('ID',username[0].username,max_age=100) self.redirect(nextname) else: self.render('authenticated.html',nextname=nextname)
頁面代碼做如下的改變就行:
<form method="post" action="/login?next={{nextname}}"> <p>用戶名<br><input type="text" name="name"></p> <p>密碼<br><input type="text" name="password"></p> <input type="submit"> </form>
配合使用模板的傳參,可以很方便的進行跳轉。
3.session
cookie中不能存放存放用戶的敏感信息,那么cookie里面就只能存放一些隨機的字符串,但是如果這樣的話,那么服務器端又怎樣知道是那個用戶呢?
我們可以建立一個會話來做這件事情,這個會話里面會存儲隨機字符串和可以唯一確定用戶的信息。
由於tornado沒有內置session模塊,所以使用pycket這個模塊中封裝好的session模塊來,要想使用首先要安裝:
pip install pyckey
pip install redis
安裝好之后就可以使用了,使用很簡單,注意一下幾點:
from pycket.session import SessionMixin # 1.在Application添加 pycket 的配置 pycket={ 'engine': 'redis', 'storage': { 'host': 'localhost', 'port': 6379, 'db_sessions': 5, 'db_notifications': 11, 'max_connections': 2**31, }, 'cookies': { 'expires_days': 30, 'max_age': 100 }, }, # 2.改 self.set_secure_cookie 為 self.session.set # self.set_secure_cookie('ID',username[0].username,max_age=100) self.session.set('user',username[0].username) # 3.改 self.get_secure_cookie 為 self.session.get # current_user = self.get_secure_cookie('ID') current_user = self.session.get('user')
以上就可以使用`session`了,這個`session`的工作原理是如下:
1. 使用`set`方法,為輸入的用戶信息生成一串隨機字符串
2. 將這個字符串和對應的用戶信息做成鍵值對,放到`redis`數據庫中
3. 將字符串處理之后放入到`cookie`中,發送給瀏覽器
4. 瀏覽器請求時將`cookie`中的信息發送到服務器,`tornado`接受到之后解析出來,去`redis`查找,找到就驗證成功
使用`session`有如下好處:
1. 可以不要在`cookie`中存放敏感信息
2. 減少數據傳輸需要的時間
3. 減少加密解密的時間
`session`的使用很簡單,但是安全性會有一個很大的提升,因此使用非常多,一定要掌握使用方法。
4.跨站防偽造請求的防范
跨站偽造請求(Cross-site request forgery)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), 簡稱為 `XSRF`,是個性化 Web 應用中常見的一個安全問題。前面的鏈接也詳細講述了` XSRF `攻擊的實現方式。
當前防范` XSRF` 的一種通用的方法,是對每一個用戶都記錄一個無法預知的` cookie `數據,然后要求所有提交的請求中都必須帶有這個` cookie `數據。如果此數據不匹配 ,那么這個請求就可能是被偽造的。
`Tornado `有內建的 `XSRF `的防范機制,要使用此機制,只需要在模板中添加如下代碼:
<form method="post" action="/login?next={{nextname}}"> {% module xsrf_form_html() %} <!--添加這行代碼就可以了--> <p>用戶名<br><input type="text" name="name"></p> <p>密碼<br><input type="text" name="password"></p> <input type="submit">