摘要:譯者說于年月日發(fā)布,該版本正式支持的關(guān)鍵字,并且用舊版本編譯同樣可以使用這兩個(gè)關(guān)鍵字,這無疑是一種進(jìn)步。其次,這是最后一個(gè)支持和的版本了,在后續(xù)的版本了會移除對它們的兼容。
譯者說
Tornado 4.3于2015年11月6日發(fā)布,該版本正式支持Python3.5的async/await關(guān)鍵字,并且用舊版本CPython編譯Tornado同樣可以使用這兩個(gè)關(guān)鍵字,這無疑是一種進(jìn)步。其次,這是最后一個(gè)支持Python2.6和Python3.2的版本了,在后續(xù)的版本了會移除對它們的兼容?,F(xiàn)在網(wǎng)絡(luò)上還沒有Tornado4.3的中文文檔,所以為了讓更多的朋友能接觸并學(xué)習(xí)到它,我開始了這個(gè)翻譯項(xiàng)目,希望感興趣的小伙伴可以一起參與翻譯,項(xiàng)目地址是tornado-zh on Github,翻譯好的文檔在Read the Docs上直接可以看到。歡迎Issues or PR。
認(rèn)證和安全 Cookies 和 secure cookies你可以在用戶瀏覽器中通過set_cookie方法設(shè)置 cookie:
class MainHandler(tornado.web.RequestHandler): def get(self): if not self.get_cookie("mycookie"): self.set_cookie("mycookie", "myvalue") self.write("Your cookie was not set yet!") else: self.write("Your cookie was set!")
普通的cookie并不安全, 可以通過客戶端修改. 如果你需要通過設(shè)置cookie,例如來識別當(dāng)前登錄的用戶, 就需要給你的cookie簽名防止偽造. Tornado支持通過 RequestHandler.set_secure_cookie 和RequestHandler.get_secure_cookie 方法對cookie簽名. 想要使用這些方法, 你需要在你創(chuàng)建應(yīng)用的時(shí)候, 指定一個(gè)名為cookie_secret的密鑰. 你可以在應(yīng)用的設(shè)置中以關(guān)鍵字參數(shù)的形式傳遞給應(yīng)用程序:
application = tornado.web.Application([ (r"/", MainHandler), ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
簽名后的cookie除了時(shí)間戳和一個(gè)HMAC 簽名還包含編碼后的cookie值. 如果cookie過期或者簽名不匹配,get_secure_cookie將返回None就像沒有設(shè)置cookie一樣. 上面例子的安全版本:
class MainHandler(tornado.web.RequestHandler): def get(self): if not self.get_secure_cookie("mycookie"): self.set_secure_cookie("mycookie", "myvalue") self.write("Your cookie was not set yet!") else: self.write("Your cookie was set!")
Tornado的安全cookie保證完整性但是不保證機(jī)密性. 也就是說, cookie不能被修改但是它的內(nèi)容對用戶是可見的. 密鑰cookie_secret是一個(gè)對稱的key, 而且必須保密--任何獲得這個(gè)key的人都可以偽造出自己簽名的cookie.
默認(rèn)情況下, Tornado的安全cookie過期時(shí)間是30天. 可以給set_secure_cookie使用expires_days關(guān)鍵字參數(shù) 同時(shí)get_secure_cookie設(shè)置max_age_days參數(shù)也可以達(dá)到效果. 這兩個(gè)值分別通過這樣(設(shè)置)你就可以達(dá)到如下的效果, 例如大多數(shù)情況下有30天有效期的cookie, 但是對某些敏感操作(例如修改賬單信息)你可以使用一個(gè)較小的max_age_days.
Tornado也支持多簽名密鑰, 使簽名密鑰輪換.cookie_secret然后必須是一個(gè)以整數(shù)key版本作為key, 以相對應(yīng)的密鑰作為值的字典. 當(dāng)前使用的簽名鍵必須是 應(yīng)用設(shè)置中key_version的集合. 不過字典中的其他key都允許做cookie簽名驗(yàn)證, 如果當(dāng)前key版本在cookie集合中.為了實(shí)現(xiàn)cookie更新, 可以通過RequestHandler.get_secure_cookie_key_version 查詢當(dāng)前key版本.
用戶認(rèn)證當(dāng)前已經(jīng)通過認(rèn)證的用戶在每個(gè)請求處理函數(shù)中都可以通過self.current_user 得到, 在每個(gè)模板中可以使用current_user獲得. 默認(rèn)情況下,current_user是None.
為了在你的應(yīng)用程序中實(shí)現(xiàn)用戶認(rèn)證, 你需要在你的請求處理函數(shù)中復(fù)寫get_current_user()方法來判斷當(dāng)前用戶, 比如可以基于cookie的值.這里有一個(gè)例子, 這個(gè)例子允許用戶簡單的通過一個(gè)保存在cookie中的特殊昵稱登錄到應(yīng)用程序中:
class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("user") class MainHandler(BaseHandler): def get(self): if not self.current_user: self.redirect("/login") return name = tornado.escape.xhtml_escape(self.current_user) self.write("Hello, " + name) class LoginHandler(BaseHandler): def get(self): self.write("") def post(self): self.set_secure_cookie("user", self.get_argument("name")) self.redirect("/") application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
你可以使用 Python裝飾器(decorator)tornado.web.authenticated 要求用戶登錄. 如果請求方法帶有這個(gè)裝飾器并且用戶沒有登錄, 用戶將會被重定向到login_url(另一個(gè)應(yīng)用設(shè)置).上面的例子可以被重寫:
class MainHandler(BaseHandler): @tornado.web.authenticated def get(self): name = tornado.escape.xhtml_escape(self.current_user) self.write("Hello, " + name) settings = { "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login", } application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), ], **settings)
如果你使用authenticated裝飾post()方法并且用戶沒有登錄,服務(wù)將返回一個(gè)403響應(yīng).@authenticated裝飾器是if not self.current_user: self.redirect()的簡寫. 可能不適合非基于瀏覽器的登錄方案.
通過 Tornado Blog example application可以看到一個(gè)使用用戶驗(yàn)證(并且在MySQL數(shù)據(jù)庫中存儲用戶數(shù)據(jù))的完整例子.
第三方用戶驗(yàn)證tornado.auth 模塊實(shí)現(xiàn)了對一些網(wǎng)絡(luò)上最流行的網(wǎng)站的身份認(rèn)證和授權(quán)協(xié)議,包括Google/Gmail, Facebook, Twitter,和FriendFeed. 該模塊包括通過這些網(wǎng)站登錄用戶的方法, 并在適用情況下允許訪問該網(wǎng)站服務(wù)的方法, 例如, 下載一個(gè)用戶的地址簿或者在他們支持下發(fā)布一條Twitter信息.
這是個(gè)使用Google身份認(rèn)證, 在cookie中保存Google的認(rèn)證信息以供之后訪問的示例處理程序:
class GoogleOAuth2LoginHandler(tornado.web.RequestHandler, tornado.auth.GoogleOAuth2Mixin): @tornado.gen.coroutine def get(self): if self.get_argument("code", False): user = yield self.get_authenticated_user( redirect_uri="http://your.site.com/auth/google", code=self.get_argument("code")) # Save the user with e.g. set_secure_cookie else: yield self.authorize_redirect( redirect_uri="http://your.site.com/auth/google", client_id=self.settings["google_oauth"]["key"], scope=["profile", "email"], response_type="code", extra_params={"approval_prompt": "auto"})
查看 tornado.auth 模塊的文檔以了解更多細(xì)節(jié).
跨站請求偽造(防護(hù))跨站請求偽造(Cross-site request forgery),或XSRF, 是所有web應(yīng)用程序面臨的一個(gè)主要問題. 可以通過Wikipedia 文章來了解更多關(guān)于XSRF的細(xì)節(jié).
普遍接受的預(yù)防XSRF攻擊的方案是讓每個(gè)用戶的cookie都是不確定的值, 并且把那個(gè)cookie值在你站點(diǎn)的每個(gè)form提交中作為額外的參數(shù)包含進(jìn)來. 如果cookie和form提交中的值不匹配, 則請求可能是偽造的.
Tornado內(nèi)置XSRF保護(hù). 你需要在你的應(yīng)用設(shè)置中使用xsrf_cookies便可以在你的網(wǎng)站上使用:
settings = { "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login", "xsrf_cookies": True, } application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), ], **settings)
如果設(shè)置了xsrf_cookies, Tornado web應(yīng)用程序?qū)o所有用戶設(shè)置_xsrfcookie并且拒絕所有不包含一個(gè)正確的_xsrf值的POST,PUT, 或DELETE請求. 如果你打開這個(gè)設(shè)置, 你必須給所有通過POST請求的form提交添加這個(gè)字段. 你可以使用一個(gè)特性的UIModule`xsrf_form_html()`來做這件事情, 這個(gè)方法在所有模板中都是可用的:
如果你提交一個(gè)AJAX的POST請求, 你也需要在每個(gè)請求中給你的JavaScript添加_xsrf值. 這是我們在FriendFeed為了AJAX的POST請求使用的一個(gè) jQuery函數(shù),可以自動的給所有請求添加_xsrf值:
function getCookie(name) { var r = document.cookie.match("" + name + "=([^;]*)"); return r ? r[1] : undefined; } jQuery.postJSON = function(url, args, callback) { args._xsrf = getCookie("_xsrf"); $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST", success: function(response) { callback(eval("(" + response + ")")); }}); };
對于PUT和DELETE請求(除了不使用form編碼(form-encoded) 參數(shù)的POST請求, XSRF token也會通過一個(gè)X-XSRFToken的HTTP頭傳遞.XSRF cookie 通常在使用xsrf_form_html會設(shè)置, 但是在不使用正規(guī)form的純Javascript應(yīng)用中, 你可能需要訪問self.xsrf_token手動設(shè)置(只讀這個(gè)屬性足夠設(shè)置cookie了).
如果你需要自定義每一個(gè)處理程序基礎(chǔ)的XSRF行為, 你可以復(fù)寫RequestHandler.check_xsrf_cookie(). 例如, 如果你有一個(gè)沒有使用cookie驗(yàn)證的API, 你可能想禁用XSRF保護(hù), 可以通過使check_xsrf_cookie()不做任何處理. 然而, 如果你支持基于cookie和非基于cookie的認(rèn)證, 重要的是,當(dāng)前帶有cookie認(rèn)證的請求究竟什么時(shí)候使用XSRF保護(hù).
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/37721.html
摘要:譯者說于年月日發(fā)布,該版本正式支持的關(guān)鍵字,并且用舊版本編譯同樣可以使用這兩個(gè)關(guān)鍵字,這無疑是一種進(jìn)步。其次,這是最后一個(gè)支持和的版本了,在后續(xù)的版本了會移除對它們的兼容。本節(jié)感謝翻譯本節(jié)最好直接在或者閱讀,以獲得更好的閱讀體驗(yàn)格式支持。 譯者說 Tornado 4.3于2015年11月6日發(fā)布,該版本正式支持Python3.5的async/await關(guān)鍵字,并且用舊版本CPython...
閱讀 3031·2021-11-12 10:36
閱讀 4773·2021-09-22 10:57
閱讀 1584·2021-09-22 10:53
閱讀 2673·2019-08-30 15:55
閱讀 3504·2019-08-29 17:00
閱讀 3362·2019-08-29 16:36
閱讀 2478·2019-08-29 13:46
閱讀 1356·2019-08-26 11:45