tornado 之authenticated和session 簡單登錄


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">

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM