欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python中JWT用戶認(rèn)證的實(shí)現(xiàn)

 更新時(shí)間:2020年05月18日 10:39:36   作者:hsw Come on  
這篇文章主要介紹了python中JWT用戶認(rèn)證的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

在前后端分離開發(fā)時(shí)為什么需要用戶認(rèn)證呢?原因是由于HTTP協(xié)定是不儲(chǔ)存狀態(tài)的(stateless),這意味著當(dāng)我們透過帳號(hào)密碼驗(yàn)證一個(gè)使用者時(shí),當(dāng)下一個(gè)request請(qǐng)求時(shí)它就把剛剛的資料忘了。于是我們的程序就不知道誰是誰,就要再驗(yàn)證一次。所以為了保證系統(tǒng)安全,我們就需要驗(yàn)證用戶否處于登錄狀態(tài)。

一、傳統(tǒng)方式

前后端分離通過Restful API進(jìn)行數(shù)據(jù)交互時(shí),如何驗(yàn)證用戶的登錄信息及權(quán)限。在原來的項(xiàng)目中,使用的是最傳統(tǒng)也是最簡(jiǎn)單的方式,前端登錄,后端根據(jù)用戶信息生成一個(gè)token,并保存這個(gè)token 和對(duì)應(yīng)的用戶id到數(shù)據(jù)庫或Session中,接著把token 傳給用戶,存入瀏覽器 cookie,之后瀏覽器請(qǐng)求帶上這個(gè)cookie,后端根據(jù)這個(gè)cookie值來查詢用戶,驗(yàn)證是否過期。

但這樣做問題就很多,如果我們的頁面出現(xiàn)了 XSS 漏洞,由于 cookie 可以被 JavaScript 讀取,XSS 漏洞會(huì)導(dǎo)致用戶 token 泄露,而作為后端識(shí)別用戶的標(biāo)識(shí),cookie 的泄露意味著用戶信息不再安全。盡管我們通過轉(zhuǎn)義輸出內(nèi)容,使用 CDN 等可以盡量避免 XSS 注入,但誰也不能保證在大型的項(xiàng)目中不會(huì)出現(xiàn)這個(gè)問題。

在設(shè)置 cookie 的時(shí)候,其實(shí)你還可以設(shè)置 httpOnly 以及 secure項(xiàng)。設(shè)置 httpOnly后 cookie 將不能被 JS 讀取,瀏覽器會(huì)自動(dòng)的把它加在請(qǐng)求的 header 當(dāng)中,設(shè)置 secure的話,cookie 就只允許通過 HTTPS 傳輸。secure 選項(xiàng)可以過濾掉一些使用 HTTP 協(xié)議的 XSS 注入,但并不能完全阻止。

httpOnly 選項(xiàng)使得 JS 不能讀取到 cookie,那么 XSS 注入的問題也基本不用擔(dān)心了。但設(shè)置 httpOnly就帶來了另一個(gè)問題,就是很容易的被 XSRF,即跨站請(qǐng)求偽造。當(dāng)你瀏覽器開著這個(gè)頁面的時(shí)候,另一個(gè)頁面可以很容易的跨站請(qǐng)求這個(gè)頁面的內(nèi)容。因?yàn)?cookie 默認(rèn)被發(fā)了出去。

另外,如果將驗(yàn)證信息保存在數(shù)據(jù)庫中,后端每次都需要根據(jù)token查出用戶id,這就增加了數(shù)據(jù)庫的查詢和存儲(chǔ)開銷。若把驗(yàn)證信息保存在session中,有加大了服務(wù)器端的存儲(chǔ)壓力。那我們可不可以不要服務(wù)器去查詢呢?如果我們生成token遵循一定的規(guī)律,比如我們使用對(duì)稱加密算法來加密用戶id形成token,那么服務(wù)端以后其實(shí)只要解密該token就可以知道用戶的id是什么了。不過呢,我只是舉個(gè)例子而已,要是真這么做,只要你的對(duì)稱加密算法泄露了,其他人可以通過這種加密方式進(jìn)行偽造token,那么所有用戶信息都不再安全了。恩,那用非對(duì)稱加密算法來做呢,其實(shí)現(xiàn)在有個(gè)規(guī)范就是這樣做的,就是我們接下來要介紹的 JWT。

二、Json Web Token(JWT)

WT 是一個(gè)開放標(biāo)準(zhǔn)(RFC 7519),它定義了一種用于簡(jiǎn)潔,自包含的用于通信雙方之間以 JSON 對(duì)象的形式安全傳遞信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對(duì)進(jìn)行簽名。它具備兩個(gè)特點(diǎn):

  • 簡(jiǎn)潔(Compact)

可以通過URL, POST 參數(shù)或者在 HTTP header 發(fā)送,因?yàn)閿?shù)據(jù)量小,傳輸速度快

  • 自包含(Self-contained)

負(fù)載中包含了所有用戶所需要的信息,避免了多次查詢數(shù)據(jù)庫

JWT 組成

Header 頭部

頭部包含了兩部分,token 類型和采用的加密算法

{
 "alg": "HS256",
 "typ": "JWT"
}

它會(huì)使用 Base64 編碼組成 JWT 結(jié)構(gòu)的第一部分,如果你使用Node.js,可以用Node.js的包base64url來得到這個(gè)字符串。
------------ Base64是一種編碼,也就是說,它是可以被翻譯回原來的樣子來的。它并不是一種加密過程。

Payload 負(fù)載

負(fù)載就是存放有效信息的地方。這些有效信息包含三個(gè)部分:
----標(biāo)準(zhǔn)中注冊(cè)聲明
----公共的聲明
----私有的聲明

公共的聲明:

公共的聲明可以添加任何的信息,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息.但不建議添加敏感信息,因?yàn)樵摬糠衷诳蛻舳丝山饷堋?/p>

私有的聲明:

私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息,因?yàn)閎ase64是對(duì)稱解密的,意味著該部分信息可以歸類為明文信息

{
  "iss": "lion1ou JWT",
  "iat": 1441593502,
  "exp": 1441594722,
  "aud": "www.example.com",
  "sub": "lion1ou@163.com"
}

// 包括需要傳遞的用戶信息;
{ 
 "iss": "Online JWT Builder", 
 "iat": 1416797419, 
 "exp": 1448333419, 
 "aud": "www.gusibi.com", 
 "sub": "uid", 
 "nickname": "goodspeed", 
 "username": "goodspeed", 
 "scopes": [ "admin", "user" ] 
}
  • iss: 該JWT的簽發(fā)者,是否使用是可選的;
  • sub: 該JWT所面向的用戶,是否使用是可選的;
  • aud: 接收該JWT的一方,是否使用是可選的;
  • exp(expires): 什么時(shí)候過期,這里是一個(gè)Unix時(shí)間戳,是否使用是可選的;
  • iat(issued at): 在什么時(shí)候簽發(fā)的(UNIX時(shí)間),是否使用是可選的;

其他還有:

  • nbf (Not Before):如果當(dāng)前時(shí)間在nbf里的時(shí)間之前,則Token不被接受;一般都會(huì)留一些余地,比如幾分鐘;,是否使用是可選的;
  • jti: jwt的唯一身份標(biāo)識(shí),主要用來作為一次性token,從而回避重放攻擊。
  • 同樣的,它會(huì)使用 Base64 編碼組成 JWT 結(jié)構(gòu)的第二部分。
  • Signature 簽名

前面兩部分都是使用 Base64 進(jìn)行編碼的,即前端可以解開知道里面的信息。Signature 需要使用編碼后的 header 和 payload 以及我們提供的一個(gè)密鑰,然后使用 header 中指定的簽名算法(HS256)進(jìn)行簽名。簽名的作用是保證 JWT 沒有被篡改過。

// 根據(jù)alg算法與私有秘鑰進(jìn)行加密得到的簽名字串;
// 這一段是最重要的敏感信息,只能在服務(wù)端解密;
HMACSHA256( 
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  SECREATE_KEY
)

三個(gè)部分通過.連接在一起就是我們的 JWT 了,它可能長(zhǎng)這個(gè)樣子,長(zhǎng)度貌似和你的加密算法和私鑰有關(guān)系。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU3ZmVmMTY0ZTU0YWY2NGZmYzUzZGJkNSIsInhzcmYiOiI0ZWE1YzUwOGE2NTY2ZTc2MjQwNTQzZjhmZWIwNmZkNDU3Nzc3YmUzOTU0OWM0MDE2NDM2YWZkYTY1ZDIzMzBlIiwiaWF0IjoxNDc2NDI3OTMzfQ.PA3QjeyZSUh7H0GfE0vJaKW4LjKJuC3dVLQiY4hii8s

其實(shí)到這一步可能就有人會(huì)想了,HTTP 請(qǐng)求總會(huì)帶上 token,這樣這個(gè) token 傳來傳去占用不必要的帶寬啊。如果你這么想了,那你可以去了解下 HTTP2,HTTP2 對(duì)頭部進(jìn)行了壓縮,相信也解決了這個(gè)問題。

簽名的目的

最后一步簽名的過程,實(shí)際上是對(duì)頭部以及負(fù)載內(nèi)容進(jìn)行簽名,防止內(nèi)容被竄改。如果有人對(duì)頭部以及負(fù)載的內(nèi)容解碼之后進(jìn)行修改,再進(jìn)行編碼,最后加上之前的簽名組合形成新的JWT的話,那么服務(wù)器端會(huì)判斷出新的頭部和負(fù)載形成的簽名和JWT附帶上的簽名是不一樣的。如果要對(duì)新的頭部和負(fù)載進(jìn)行簽名,在不知道服務(wù)器加密時(shí)用的密鑰的話,得出來的簽名也是不一樣的。

信息暴露

在這里大家一定會(huì)問一個(gè)問題:Base64是一種編碼,是可逆的,那么我的信息不就被暴露了嗎?

是的。所以,在JWT中,不應(yīng)該在負(fù)載里面加入任何敏感的數(shù)據(jù)。在上面的例子中,我們傳輸?shù)氖怯脩舻腢ser ID。這個(gè)值實(shí)際上不是什么敏感內(nèi)容,一般情況下被知道也是安全的。但是像密碼這樣的內(nèi)容就不能被放在JWT中了。如果將用戶的密碼放在了JWT中,那么懷有惡意的第三方通過Base64解碼就能很快地知道你的密碼了。

因此JWT適合用于向Web應(yīng)用傳遞一些非敏感信息。JWT還經(jīng)常用于設(shè)計(jì)用戶認(rèn)證和授權(quán)系統(tǒng),甚至實(shí)現(xiàn)Web應(yīng)用的單點(diǎn)登錄。

token 生成好之后,接下來就可以用token來和服務(wù)器進(jìn)行通訊了。

三、JWT 使用

下圖是client 使用 JWT 與server 交互過程:

 

1.這里在第三步我們得到 JWT 之后,需要將JWT存放在 client,之后的每次需要認(rèn)證的請(qǐng)求都要把JWT發(fā)送過來。(請(qǐng)求時(shí)可以放到 header 的 Authorization )
首先,前端通過Web表單將自己的用戶名和密碼發(fā)送到后端的接口。這一過程一般是一個(gè)HTTP POST請(qǐng)求。建議的方式是通過SSL加密的傳輸(https協(xié)議),從而避免敏感信息被嗅探。

2.后端核對(duì)用戶名和密碼成功后,將用戶的id等其他信息作為JWT Payload(負(fù)載),將其與頭部分別進(jìn)行Base64編碼拼接后簽名,形成一個(gè)JWT。形成的JWT就是一個(gè)形同lll.zzz.xxx的字符串。

3.后端將JWT字符串作為登錄成功的返回結(jié)果返回給前端。前端可以將返回的結(jié)果保存在localStorage或sessionStorage上,退出登錄時(shí)前端刪除保存的JWT即可。

4.前端在每次請(qǐng)求時(shí)將JWT放入HTTP Header中的Authorization位。(解決XSS和XSRF問題)

5.后端檢查是否存在,如存在驗(yàn)證JWT的有效性。例如,檢查簽名是否正確;檢查Token是否過期;檢查Token的接收方是否是自己(可選)。

6.驗(yàn)證通過后后端使用JWT中包含的用戶信息進(jìn)行其他邏輯操作,返回相應(yīng)結(jié)果。

四、JWT 使用場(chǎng)景

WT的主要優(yōu)勢(shì)在于使用無狀態(tài)、可擴(kuò)展的方式處理應(yīng)用中的用戶會(huì)話。服務(wù)端可以通過內(nèi)嵌的聲明信息,很容易地獲取用戶的會(huì)話信息,而不需要去訪問用戶或會(huì)話的數(shù)據(jù)庫。在一個(gè)分布式的面向服務(wù)的框架中,這一點(diǎn)非常有用。

但是,如果系統(tǒng)中需要使用黑名單實(shí)現(xiàn)長(zhǎng)期有效的token刷新機(jī)制,這種無狀態(tài)的優(yōu)勢(shì)就不明顯了。

優(yōu)點(diǎn)
快速開發(fā)
不需要cookie
JSON在移動(dòng)端的廣泛應(yīng)用
不依賴于社交登錄
相對(duì)簡(jiǎn)單的概念理解

缺點(diǎn)
Token有長(zhǎng)度限制
Token不能撤銷
需要token有失效時(shí)間限制(exp)

五、和Session方式存儲(chǔ)id的差異

Session方式存儲(chǔ)用戶id的最大弊病在于Session是存儲(chǔ)在服務(wù)器端的,所以需要占用大量服務(wù)器內(nèi)存,對(duì)于較大型應(yīng)用而言可能還要保存許多的狀態(tài)。一般而言,大型應(yīng)用還需要借助一些KV數(shù)據(jù)庫和一系列緩存機(jī)制來實(shí)現(xiàn)Session的存儲(chǔ)。

而JWT方式將用戶狀態(tài)分散到了客戶端中,可以明顯減輕服務(wù)端的內(nèi)存壓力。除了用戶id之外,還可以存儲(chǔ)其他的和用戶相關(guān)的信息,例如該用戶是否是管理員、用戶所在的分組等。雖說JWT方式讓服務(wù)器有一些計(jì)算壓力(例如加密、編碼和解碼),但是這些壓力相比磁盤存儲(chǔ)而言可能就不算什么了。具體是否采用,需要在不同場(chǎng)景下用數(shù)據(jù)說話。

單點(diǎn)登錄

Session方式來存儲(chǔ)用戶id,一開始用戶的Session只會(huì)存儲(chǔ)在一臺(tái)服務(wù)器上。對(duì)于有多個(gè)子域名的站點(diǎn),每個(gè)子域名至少會(huì)對(duì)應(yīng)一臺(tái)不同的服務(wù)器,例如:www.taobao.com,nv.taobao.com,nz.taobao.com,login.taobao.com。所以如果要實(shí)現(xiàn)在login.taobao.com登錄后,在其他的子域名下依然可以取到Session,這要求我們?cè)诙嗯_(tái)服務(wù)器上同步Session。使用JWT的方式則沒有這個(gè)問題的存在,因?yàn)橛脩舻臓顟B(tài)已經(jīng)被傳送到了客戶端。

六、總結(jié)

JWT的主要作用在于:
(一)可附帶用戶信息,后端直接通過JWT獲取相關(guān)信息。
(二)使用本地保存,通過HTTP Header中的Authorization位提交驗(yàn)證。

七、附加,python使用JWT

python 中djagno rest framework要使用jwt,可以使用以下這個(gè)模塊:githubs文檔有使用說明
https://github.com/GetBlimp/django-rest-framework-jwt

pip install djangorestframework-jwt

不是使用django的話,我們可以使用 pyjwt:
https://github.com/jpadilla/pyjwt/
使用比較方便,下邊是我在應(yīng)用中使用的例子:

import jwt
import time

# 使用 sanic 作為restful api 框架 
def create_token(request):
  grant_type = request.json.get('grant_type')
  username = request.json['username']
  password = request.json['password']
  if grant_type == 'password':
    account = verify_password(username, password)
  elif grant_type == 'wxapp':
    account = verify_wxapp(username, password)
  if not account:
    return {}
  payload = {
    "iss": "gusibi.com",
     "iat": int(time.time()),
     "exp": int(time.time()) + 86400 * 7,
     "aud": "www.gusibi.com",
     "sub": account['_id'],
     "username": account['username'],
     "scopes": ['open']
  }
  token = jwt.encode(payload, 'secret', algorithm='HS256')
  return True, {'access_token': token, 'account_id': account['_id']}
  

def verify_bearer_token(token):
  # 如果在生成token的時(shí)候使用了aud參數(shù),那么校驗(yàn)的時(shí)候也需要添加此參數(shù)
  payload = jwt.decode(token, 'secret', audience='www.gusibi.com', algorithms=['HS256'])
  if payload:
    return True, token
  return False, token

到此這篇關(guān)于python中JWT用戶認(rèn)證的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)python JWT用戶認(rèn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • python中的錯(cuò)誤處理及異常斷言詳解

    python中的錯(cuò)誤處理及異常斷言詳解

    這篇文章主要為大家介紹了python中的錯(cuò)誤處理及異常斷言示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 基于Python在MacOS上安裝robotframework-ride

    基于Python在MacOS上安裝robotframework-ride

    今天小編就為大家分享一篇關(guān)于基于Python在MacOS上安裝robotframework-ride,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • windows下wxPython開發(fā)環(huán)境安裝與配置方法

    windows下wxPython開發(fā)環(huán)境安裝與配置方法

    這篇文章主要介紹了windows下wxPython開發(fā)環(huán)境安裝與配置方法,需要的朋友可以參考下
    2014-06-06
  • python 處理數(shù)字,把大于上限的數(shù)字置零實(shí)現(xiàn)方法

    python 處理數(shù)字,把大于上限的數(shù)字置零實(shí)現(xiàn)方法

    今天小編就為大家分享一篇python 處理數(shù)字,把大于上限的數(shù)字置零實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • Django中使用Celery的方法步驟

    Django中使用Celery的方法步驟

    這篇文章主要介紹了Django中使用Celery,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 基于Python制作一個(gè)解壓的內(nèi)存加速球

    基于Python制作一個(gè)解壓的內(nèi)存加速球

    安全管家助手什么的上總會(huì)帶一個(gè)內(nèi)存加速球,有關(guān)掉進(jìn)程以及內(nèi)存清理的功能,本文就來利用Python制作一個(gè)解壓的內(nèi)存加速球,有需要的小伙伴可以參考下
    2023-10-10
  • Python基于回溯法子集樹模板解決m著色問題示例

    Python基于回溯法子集樹模板解決m著色問題示例

    這篇文章主要介紹了Python基于回溯法子集樹模板解決m著色問題,簡(jiǎn)單描述了m著色問題并結(jié)合實(shí)例形式分析了Python使用回溯法子集樹模板解決m著色問題的具體步驟與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2017-09-09
  • Python中@符號(hào)的具體使用

    Python中@符號(hào)的具體使用

    本文主要介紹了Python中@符號(hào)的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Python實(shí)現(xiàn)接口自動(dòng)化測(cè)試的方法詳解

    Python實(shí)現(xiàn)接口自動(dòng)化測(cè)試的方法詳解

    Python接口自動(dòng)化測(cè)試是一種高效、可重復(fù)的軟件質(zhì)量驗(yàn)證方法,尤其在現(xiàn)代軟件開發(fā)中,它已經(jīng)成為不可或缺的一部分,本文將深入探討如何使用Python進(jìn)行接口自動(dòng)化測(cè)試,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • Python中的hypot()方法使用簡(jiǎn)介

    Python中的hypot()方法使用簡(jiǎn)介

    這篇文章主要介紹了Python中的hypot()方法使用簡(jiǎn)介,是Python入門所需掌握的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-05-05

最新評(píng)論