Tornado(cookie、XSRF、用戶驗證)
1、設置Cookie
1、set_cookie(name,value,domain=None,expires=None,path="/")
2、參數說明: 1、name:cookie名 2、value:cookie值 3、domain:提交cookie時匹配的域名 4、path:提交cookie時匹配的路徑 5、expires:cookie的有效期,可以是時間戳整數、時間元組或者datetime類型,為UTC時間 6、expires_days:cookie的有效期,天數,優先級低於expires 3、實例: import datetime class IndexHandler(RequestHandler): def get(self): self.set_cookie("n1", "v1") self.set_cookie("n2", "v2", path="/new", expires=time.strptime("2016-11-11 23:59:59","%Y-%m-%d %H:%M:%S")) self.set_cookie("n3", "v3", expires_days=20) # 利用time.mktime將本地時間轉換為UTC標準時間 self.set_cookie("n4", "v4", expires=time.mktime(time.strptime("2016-11-11 23:59:59","%Y-%m-%d %H:%M:%S"))) self.write("OK")
2、原理:
1、設置cookie實際就是通過設置header的Set-Cookie來實現的。
2、實例:
[AppleScript] 純文本查看 復制代碼
?
1
2
3
4
5
6
7
class IndexHandler(RequestHandler):
def get(self):
self.set_header("Set-Cookie", "n5=v5; expires=Fri, 11 Nov 2016 15:59:59 GMT; Path=/")
self.write("OK")
3、獲取cookie
1、get_cookie(name, default=None)
2、參數說明:
1、name:要獲取的cookie的民稱
2、default:如果數據不存在,可設置默認值
3、實例:
class IndexHandler(RequestHandler):
def get(self):
n3 = self.get_cookie("n3")
self.write(n3)
4、清楚cookie
1、clear_cookie(name, path=‘/‘, domain=None):
刪除名為name,並同時匹配domain和path的cookie。
2、clear_all_cookies(path=‘/‘, domain=None): 刪除同時匹配domain和path的所有cookie。 3、實例: 4、註意:執行清除cookie操作後,並不是立即刪除了瀏覽器中的cookie,而是給cookie值置空,並改變其有效期使其失效。真正的刪除cookie是由瀏覽器去清理的。
5、安全Cookie
1、Cookie是存儲在客戶端瀏覽器中的,很容易被篡改。Tornado提供了一種對Cookie進行簡易加密簽名的方法來防止Cookie被惡意篡改。
2、使用安全Cookie需要為應用配置一個用來給Cookie進行混淆的秘鑰cookie_secret,將其傳遞給Application的構造函數。可以使用如下方法來生成一個隨機字符串作為cookie_secret的值:
>ipython
>import base64,uuid
>base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)
3、將生成的cookie_secret傳入Application的構造函數:
[AppleScript] 純文本查看 復制代碼
?
1
2
3
4
5
6
7
8
9
class ClearOneCookieHandler(RequestHandler):
def get(self):
self.clear_cookie("n3")
self.write("OK")
class ClearAllCookieHandler(RequestHandler):
def get(self):
self.clear_all_cookies()
self.write("OK")
4、set_secure_cookie(name, value, expires_days=30):
設置一個帶簽名和時間戳的cookie,防止cookie被偽造。
5、get_secure_cookie(name, value=None, max_age_days=31):
如果cookie存在且驗證通過,返回cookie的值,否則返回None。max_age_day不同於expires_days,expires_days是設置瀏覽器中cookie的有效期,而max_age_day是過濾安全cookie的時間戳。
6、實例:
[AppleScript] 純文本查看 復制代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
class IndexHandler(RequestHandler):
def get(self):
cookie = self.get_secure_cookie("count")
count = int(cookie) + 1 if cookie else 1
self.set_secure_cookie("count", str(count))
self.write(
‘<html><head><title>Cookie計數器</title></head>‘
‘<body><h1>您已訪問本頁%d次。</h1>‘ % count +
‘</body></html>‘
)
--------------------XSRF保護--------------------
1、XSRF保護概念:
1、瀏覽器有一個很重要的概念——同源策略(Same-Origin Policy)。所謂同源是指,域名,協議,端口相同。 不同源的客戶端腳本(javascript、ActionScript)在沒明確授權的情況下,不能讀寫對方的資源。
2、由於第三方站點沒有訪問cookie數據的權限(同源策略),所以可以要求每個請求包括一個特定的參數值作為令牌來匹配存儲在cookie中的對應值,如果兩者匹配,的應用認定請求有效。而第三方站點無法在請求中包含令牌cookie值,這就有效地防止了不可信網站發送未授權的請求。
[AppleScript] 純文本查看 復制代碼
?
1
2
3
4
5
6
7
8
9
app = tornado.web.Application(
[(r"/", IndexHandler),],
cookie_secret = "2hcicVu+TqShDpfsjMWQLZ0Mkq5NPEWSk9fi0zsSt3A=",
xsrf_cookie = True
)
2、開啟XSRF保護:
1、要開啟XSRF保護,需要在Application的構造函數中添加xsrf_cookies參數:
2、當這個參數被設置時,Tornado將拒絕請求參數中不包含正確的_xsrf值的POST、PUT和DELETE請求。用不帶_xsrf的post請求時,報出了HTTP 403: Forbidden (‘_xsrf‘ argument missing from POST)的錯誤。
3、應用
1、模板中應用
在模板中添加:{% module xsrf_form_html() %}
2、非模板中應用
1、在任意的Handler中通過獲取self.xsrf_token的值來生成_xsrf並設置Cookie:
1、方法一:
class XSRFTokenHandler(RequestHandler):
"""專門用來設置_xsrf Cookie的接口"""
def get(self):
self.xsrf_token
self.write("Ok")
2、方法二:
class StaticFileHandler(tornado.web.StaticFileHandler):
"""重寫StaticFileHandler,構造時觸發設置_xsrf Cookie"""
def __init__(self, *args, **kwargs):
super(StaticFileHandler, self).__init__(*args, **kwargs)
self.xsrf_token
3、對於請求攜帶_xsrf參數,有兩種方式:
1、若請求體是表單編碼格式的,可以在請求體中添加_xsrf參數
//AJAX發送post請求,表單格式數據
function xsrfPost() {
var xsrf = getCookie("_xsrf");
$.post("/new", "_xsrf="+xsrf+"&key1=value1", function(data) {
alert("OK");
});
}
2、若請求體是其他格式的(如json或xml等),可以通過設置HTTP頭X-XSRFToken來傳遞_xsrf值
$.ajax({
url: "/new",
method: "POST",
headers: {
"X-XSRFToken":xsrf,
},
data:json_data,
success:function(data) {
alert("OK");
}
})
--------------------用戶驗證--------------------
1、概念:
用戶驗證是指在收到用戶請求後進行處理前先判斷用戶的認證狀態(如登陸狀態),若通過驗證則正常處理,否則強制用戶跳轉至認證頁面(如登陸頁面)。
2、authenticated裝飾器
1、為了使用Tornado的認證功能,需要對登錄用戶標記具體的處理函數。可以使用@tornado.web.authenticated裝飾器完成它。當使用這個裝飾器包裹一個處理方法時,Tornado將確保這個方法的主體只有在合法的用戶被發現時才會調用。
2、實例:
class ProfileHandler(RequestHandler):
@tornado.web.authenticated
def get(self):
self.write("這是我的個人主頁。")
3、get_current_user()方法
1、裝飾器@tornado.web.authenticated的判斷執行依賴於請求處理類中的self.current_user屬性,如果current_user值為假(None、False、0、""等),任何GET或HEAD請求都將把訪客重定向到應用設置中login_url指定的URL,而非法用戶的POST請求將返回一個帶有403(Forbidden)狀態的HTTP響應。
2、在獲取self.current_user屬性的時候,tornado會調用get_current_user()方法來返回current_user的值。也就是說,驗證用戶的邏輯應寫在get_current_user()方法中,若該方法返回非假值則驗證通過,否則驗證失敗。
3、實例:
class ProfileHandler(RequestHandler):
def get_current_user(self):
"""在此完成用戶的認證邏輯"""
user_name = self.get_argument("name", None)
return user_name
@tornado.web.authenticated
def get(self):
self.write("這是我的個人主頁。")
4、login_url設置:
1、當用戶驗證失敗時,將用戶重定向到login_url上,所以還需要在Application中配置login_url。
2、實例:
class LoginHandler(RequestHandler):
def get(self):
"""在此返回登陸頁面"""
self.write("登陸頁面")
app = tornado.web.Application(
[
(r"/", IndexHandler),
(r"/profile", ProfileHandler),
(r"/login", LoginHandler),
],
"login_url":"/login"
)
3、在login_url後面補充的next參數就是記錄的跳轉至登錄頁面前的所在位置,所以可以使用next參數來完成登陸後的跳轉。
class LoginHandler(RequestHandler):
def get(self):
"""登陸處理,完成登陸後跳轉回前一頁面"""
next = self.get_argument("next", "/")
self.redirect(next+"?name=logined")
Tornado(cookie、XSRF、用戶驗證)