Json Web Token
是解決現(xiàn)在前后端分離權(quán)限驗證的方法之一阎曹。
先看幾篇參考文章:
在使用session
機制的時候斟湃,session
的本質(zhì)是在服務(wù)器中生成的一段隨機字符串,在Tornado
的單體應(yīng)用中我們可以使用set_cookie
和set_secure_cookie
通過瀏覽器將session
保存到瀏覽器的cookie
中癣缅。因為這個步操作是交給瀏覽器做的哄酝,因此前后端分離的情況的時候,這兩個方法就是沒用的了屡立。不過搀军,我們可以通過接口將session
返回給前端,前端下次查詢接口帶上session
也是可以完成前后端分離罩句,我們在后端可以攔截session
獲取到保存到session
中的信息。例如使用itsdangerous來進行加密乳愉。
JWT
的本質(zhì)是加密技術(shù),我們在服務(wù)器加密生成字符串返回給客戶端蔓姚,客戶端保存,下次查詢的之后攜帶上來泄私,服務(wù)端進行校驗备闲。相比于sesssion
保存在服務(wù)器,JWT
是不用保存的浅役。
下面我們看如何在Tornado
中集成JWT
,我們以慕課網(wǎng)實戰(zhàn)課程為例。
我們使用的模塊是pyjwt
生成加密字符串
# 構(gòu)建 json web token
# 設(shè)置過期時間要設(shè)置 UTC 時間 因為內(nèi)部檢查使用的也是 UTC 時間
payload = {
"id": user.id,
"nick_name": user.nick_name,
"exp": datetime.utcnow()
}
token = jwt.encode(payload, self.settings["secret_key"], algorithm='HS256')
re_data["token"] = token
我們將用戶的id
和nick_name
設(shè)置在payload
中瞪讼。
那把這個加密字符串返回給前端之后 怎么使用呢粹断?這就是要我們重新抒寫權(quán)限裝飾器然后使用這個token
了。
下面是我們要改寫的裝飾器瓶埋。
def authenticated_async(method):
@functools.wraps(method)
async def wrapper(self, *args, **kwargs):
tsessionid = self.request.headers.get("tsessionid", None)
if tsessionid:
# 對token過期進行異常捕捉
try:
# 從 token 中獲得我們之前存進 payload 的用戶id
send_data = jwt.decode(tsessionid, self.settings["secret_key"], leeway=self.settings["jwt_expire"],
options={"verify_exp": True})
user_id = send_data["id"]
# 從數(shù)據(jù)庫中獲取到user并設(shè)置給_current_user
try:
user = await self.application.objects.get(User, id=user_id)
self._current_user = user
# 此處需要使用協(xié)程方式執(zhí)行 因為需要裝飾的是一個協(xié)程
await method(self, *args, **kwargs)
except User.DoesNotExist as e:
self.set_status(401)
except jwt.ExpiredSignatureError as e:
self.set_status(401)
else:
self.set_status(401)
self.finish({})
return wrapper
上面展示了如何使用我們的jwt
养筒。
在需要權(quán)限的地方使用了權(quán)限裝飾器即可。
class GroupHandler(RedisHandler):
@authenticated_async
async def get(self, *args, **kwargs):
總體使用感覺在Flask
中集成itsdangerous
庫很類似挤悉。