新聞中心
Cookie
您可以使用?set_cookie?方法在用戶瀏覽器中設置 cookie:

創(chuàng)新互聯(lián)公司從2013年成立,是專業(yè)互聯(lián)網技術服務公司,擁有項目成都網站制作、做網站、外貿營銷網站建設網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元邵武做網站,已為上家服務,為邵武各地企業(yè)和個人服務,聯(lián)系電話:028-86922220
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 不安全,很容易被修改。 如果您需要設置 cookie,例如,識別當前登錄的用戶,您需要簽署您的 cookie 以防止偽造。 Tornado 支持使用 set_secure_cookie 和 get_secure_cookie 方法簽名的 cookie。 要使用這些方法,您需要在創(chuàng)建應用程序時指定一個名為 ?cookie_secret? 的密鑰。 您可以將應用程序設置作為關鍵字參數(shù)傳遞給您的應用程序:
application = tornado.web.Application([
(r"/", MainHandler),
], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")除了時間戳和 HMAC 簽名之外,簽名的 cookie 還包含 cookie 的編碼值。 如果 cookie 是舊的或者簽名不匹配,?get_secure_cookie? 將返回 ?None? ,就好像 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 保證完整性,但不保證機密性。 也就是說,cookie 無法修改,但用戶可以看到其內容。 ?cookie_secret? 是一個對稱密鑰,必須保密——任何獲得此密鑰值的人都可以生成自己的簽名 cookie。
默認情況下,Tornado 的安全 cookie 會在 30 天后過期。 要更改此設置,請使用 ?set_secure_cookie? 的 ?expires_days? 關鍵字參數(shù)和 ?get_secure_cookie? 的 ?max_age_days? 參數(shù)。 這兩個值分別傳遞,以便您可以例如 對于大多數(shù)用途,cookie 的有效期為 30 天,但對于某些敏感操作(例如更改帳單信息),您在讀取 cookie 時使用較小的 ?max_age_days?。
Tornado 還支持多個簽名密鑰以啟用簽名密鑰輪換。 那么 ?cookie_secret? 必須是一個字典,其中整數(shù)密鑰版本作為鍵,相應的秘密作為值。 然后必須將當前使用的簽名密鑰設置為 ?key_version? 應用程序設置,但如果在 cookie 中設置了正確的密鑰版本,則允許 dict 中的所有其他密鑰進行 cookie 簽名驗證。 要實現(xiàn) cookie 更新,可以通過 get_secure_cookie_key_version 查詢當前的簽名密鑰版本。
用戶認證
當前經過身份驗證的用戶在每個請求處理程序中作為 self.current_user 可用,在每個模板中作為 ?current_user? 可用。 默認情況下,?current_user? 為?None?。
要在您的應用程序中實現(xiàn)用戶身份驗證,您需要覆蓋請求處理程序中的 ?get_current_user()方法,以根據(jù)例如 cookie 的值來確定當前用戶。 下面是一個示例,用戶只需指定昵稱即可登錄應用程序,然后將昵稱保存在 cookie 中:
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 登錄。 如果一個請求使用這個裝飾器發(fā)送到一個方法,并且用戶沒有登錄,他們將被重定向到 ?login_url?(另一個應用程序設置)。 上面的例子可以重寫:
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()? 方法,并且用戶沒有登錄,服務器將發(fā)送一個 ?403? 響應。 ?@authenticated? 裝飾器只是 ?if not self.current_user: self.redirect()? 的簡寫,可能不適用于非基于瀏覽器的登錄方案。
第三方認證
tornado.auth 模塊為網絡上許多最流行的站點實現(xiàn)身份驗證和授權協(xié)議,包括 Google/Gmail、Facebook、Twitter 和 FriendFeed。 該模塊包括通過這些站點登錄用戶的方法,以及在適用的情況下授權訪問服務的方法,以便您可以下載用戶的通訊錄或代表他們發(fā)布 Twitter 消息。
這是一個使用 Google 進行身份驗證的示例處理程序,將 Google 憑據(jù)保存在 cookie 中以供以后訪問:
class GoogleOAuth2LoginHandler(tornado.web.RequestHandler,
tornado.auth.GoogleOAuth2Mixin):
async def get(self):
if self.get_argument('code', False):
user = await 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:
await 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'})跨站請求偽造保護
防止 XSRF 的普遍接受的解決方案是使用不可預測的值對每個用戶進行 cookie,并將該值作為附加參數(shù)包含在您網站上的每個表單提交中。 如果 cookie 和表單提交中的值不匹配,那么請求很可能是偽造的。
Tornado 帶有內置的 XSRF 保護。 要將其包含在您的站點中,請包含應用程序設置 ?xsrf_cookies?:
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)如果設置了 ?xsrf_cookies?,Tornado Web 應用程序將為所有用戶設置 ?_xsrf? cookie,并拒絕所有不包含正確 ?_xsrf? 值的 ?POST?、?PUT? 和 ?DELETE? 請求。 如果打開此設置,則需要檢測通過 ?POST 提交的所有表單以包含此字段。 您可以使用所有模板中可用的特殊 UIModule ?xsrf_form_html()? 來完成此操作:
如果您提交 AJAX ?POST? 請求,您還需要檢測 JavaScript 以在每個請求中包含 ?_xsrf? 值。 這是我們在 FriendFeed 中用于 AJAX ?POST? 請求的 jQuery 函數(shù),它會自動將 ?_xsrf? 值添加到所有請求中:
function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
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 ?請求(以及不使用表單編碼參數(shù)的 ?POST ?請求),XSRF 令牌也可以通過名為 ?X-XSRFToken? 的 HTTP 標頭傳遞。 XSRF cookie 通常在使用 ?xsrf_form_html? 時設置,但在不使用任何常規(guī)表單的純 JavaScript 應用程序中,您可能需要手動訪問 ?self.xsrf_token?(只需讀取屬性就足以將 cookie 設置為副作用) .
如果您需要基于每個處理程序自定義 XSRF 行為,您可以覆蓋 RequestHandler.check_xsrf_cookie()。 例如,如果您的 API 的身份驗證不使用 cookie,您可能希望通過使 ?check_xsrf_cookie()? 什么都不做來禁用 XSRF 保護。 但是,如果您同時支持 cookie 和非基于 cookie 的身份驗證,那么無論何時使用 cookie 對當前請求進行身份驗證,都必須使用 XSRF 保護。
DNS重新綁定
DNS 重新綁定是一種可以繞過同源策略并允許外部站點訪問專用網絡上的資源的攻擊。 這種攻擊涉及一個 DNS 名稱(具有短 TTL),該名稱在返回由攻擊者控制的 IP 地址和由受害者控制的 IP 地址(通常是可猜測的私有 IP 地址,例如 ?127.0.0.1? 或 ?192.168.1.1?)之間交替。
使用 TLS 的應用程序不容易受到這種攻擊(因為瀏覽器會顯示阻止自動訪問目標站點的證書不匹配警告)。
不能使用 TLS 并依賴網絡級訪問控制的應用程序(例如,假設 ?127.0.0.1? 上的服務器只能由本地計算機訪問)應通過驗證 ?Host? HTTP 表頭來防止 DNS 重新綁定。 這意味著將限制性主機名模式傳遞給 HostMatches 路由器或 Application.add_handlers 的第一個參數(shù):
# BAD: uses a default host pattern of r'.*'
app = Application([('/foo', FooHandler)])
# GOOD: only matches localhost or its ip address.
app = Application()
app.add_handlers(r'(localhost|127\.0\.0\.1)',
[('/foo', FooHandler)])
# GOOD: same as previous example using tornado.routing.
app = Application([
(HostMatches(r'(localhost|127\.0\.0\.1)'),
[('/foo', FooHandler)]),
])此外,Application 和 DefaultHostMatches 路由器的?default_host?參數(shù)不得用于可能易受 DNS 重新綁定攻擊的應用程序中,因為它與通配符主機模式具有類似的效果。
網站欄目:創(chuàng)新互聯(lián)Tornado教程:Tornado身份驗證和安全性
分享地址:http://www.5511xx.com/article/djjsipe.html


咨詢
建站咨詢
