一、什么是鑒權(quán)?為什么要鑒權(quán)
鑒權(quán)(authentication),也叫做認(rèn)證,即驗(yàn)證用戶是否擁有訪問(wèn)系統(tǒng)的權(quán)利。
HTTP本身是無(wú)狀態(tài)的請(qǐng)求,每次請(qǐng)求都是一次性的,并不會(huì)知道請(qǐng)求前后發(fā)生了什么。但在很多情況情況下都需要維護(hù)狀態(tài),最典型的就是用戶登錄系統(tǒng),并在系統(tǒng)中進(jìn)行一系列操作
API接口直接暴露在互聯(lián)網(wǎng)上是存在安全風(fēng)險(xiǎn)的,如果不進(jìn)行鑒權(quán),就有可能被網(wǎng)上的不法分子惡意攻擊(如:爬蟲,惡意訪問(wèn)等),使得api資源被非法訪問(wèn)占用,正常用戶訪問(wèn)受阻。因此鑒權(quán)十分必要,只有鑒權(quán)成功的請(qǐng)求才能請(qǐng)求服務(wù),否則就被攔截
二、Cookie/Session鑒權(quán)
為每個(gè)用戶頒發(fā)一個(gè)身份牌
為了識(shí)別用戶,可以為每個(gè)用戶設(shè)置一個(gè)“身份牌”,“身份牌”里面可以存放用戶的信息,每次請(qǐng)求的時(shí)候都帶上這個(gè)“身份牌”,這樣就可以用來(lái)識(shí)別用戶了。而這個(gè)“身份牌”就是我們經(jīng)常提到的“cookie”
Session會(huì)話的引入
隨著web應(yīng)用的告訴發(fā)展,越來(lái)越多的用戶信息需要存儲(chǔ),如果僅僅依靠Cookie字段存儲(chǔ),會(huì)大大增加每次請(qǐng)問(wèn)的負(fù)擔(dān)。
因此引入會(huì)話(session)的概念,使用一個(gè)會(huì)話ID(sessionID)映射到用戶的各種信息上,每次請(qǐng)求只需要在cookie攜帶上sessionID就可以解決cookie增長(zhǎng)的問(wèn)題
為了更好的負(fù)載均衡與容災(zāi),后端服務(wù)器一般使用分布式方式部署,一個(gè)用戶的Session信息在單臺(tái)服務(wù)器上創(chuàng)建后需要同步給其余的服務(wù)器。因此Session映射采用Redis等緩存服務(wù)器方式才能解決跨地域多機(jī)房問(wèn)題
(為了負(fù)載均衡與容災(zāi),Redis集群也需要使用多機(jī)房部署)
局限
- 依賴cookie,cookie可以被禁用,也可以被劫持篡改
- 移動(dòng)端中cookie和session機(jī)制不被支持,跨平臺(tái)不好兼容
- 緩存服務(wù)器的多機(jī)房信息同步需要時(shí)間,如果服務(wù)某個(gè)機(jī)房出現(xiàn)問(wèn)題,依然可能造成用戶Session短暫失敗
二、token授權(quán)之JWT
分散壓力
既然基于cookie的session鑒權(quán)存在上述問(wèn)題,那么能否改變一下思路,跳出以上的局限性。
Session會(huì)話機(jī)制的痛點(diǎn)在于,Session的用戶解析需要后端服務(wù)來(lái)維護(hù)邏輯,甚至還需要一個(gè)緩存服務(wù)器來(lái)維護(hù),這使得一次請(qǐng)求的鏈路變長(zhǎng),出現(xiàn)問(wèn)題的概率也比較大
那干脆讓客戶端來(lái)維護(hù)自己的用戶信息就好了,這樣大量的用戶信息就分散到各個(gè)用戶的設(shè)備上,服務(wù)器的壓力就會(huì)減少很多
客戶維護(hù)鑒權(quán)信息的機(jī)制類似于http協(xié)議也是無(wú)狀態(tài)的,這也使得整個(gè)服務(wù)拓展性大大提升
用token代替session
- 用戶第一次登錄,服務(wù)器驗(yàn)證用戶,通過(guò)后生成一個(gè)token
- 在第一次返回時(shí)將token返回給客戶端,客戶端存儲(chǔ)下來(lái),下次請(qǐng)求時(shí)攜帶上該token
- 之后只要驗(yàn)證token是否有效即可
- 為了避免篡改,可以在token中使用加密算法生成簽名,加入token(私鑰保存在服務(wù)器上,因此簽名無(wú)法被破解)
JWT(JSON Web Token)token生成標(biāo)準(zhǔn)
JSON Web Token (JWT)是一個(gè)開放標(biāo)準(zhǔn)(RFC 7519),它定義了一種緊湊的、自包含的方式,用于作為JSON對(duì)象在各方之間安全地傳輸信息。因?yàn)閿y帶了數(shù)字簽名,因此該信息可以被驗(yàn)證和信任的
JWT由三部分?jǐn)?shù)據(jù)組成,三部分由 點(diǎn)(.) 進(jìn)行分割
- Header(頭部)
- Payload(負(fù)載)
- Signature(簽名)
Header.Payload.Signature
Header
Header 部分是一個(gè) JSON 對(duì)象,描述 JWT 的元數(shù)據(jù),例如:
{
"alg": "HS256",
"typ": "JWT"
}
alg屬性表示簽名的算法(algorithm),默認(rèn)是 HMAC SHA256(寫成 HS256);typ屬性表示這個(gè)令牌(token)的類型(type),JWT 令牌統(tǒng)一寫為JWT
最后,將上面的 JSON 對(duì)象使用 Base64URL 算法轉(zhuǎn)成字符串
Payload
Payload 部分也是一個(gè) JSON 對(duì)象,用來(lái)存放實(shí)際需要傳遞的數(shù)據(jù)。JWT 規(guī)定了7個(gè)官方字段,可以從中選擇使用
iss (issuer):簽發(fā)人
exp (expiration time):過(guò)期時(shí)間
sub (subject):主題
aud (audience):受眾
nbf (Not Before):生效時(shí)間
iat (Issued At):簽發(fā)時(shí)間
jti (JWT ID):編號(hào)
當(dāng)然也可以自定義字段,不過(guò)由于這部分?jǐn)?shù)據(jù)是明文傳送,所以不要在payload字段上存放任何私密信息
Signature
Signature 部分是對(duì)前兩部分的簽名,防止數(shù)據(jù)篡改。
首先,需要指定一個(gè)密鑰(secret)。這個(gè)密鑰只有服務(wù)器才知道,不能泄露給用戶。然后使用 Header 里面指定的簽名算法(默認(rèn)是 HMAC SHA256),按照下面的公式產(chǎn)生簽名。
HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
算出簽名以后,把 Header、Payload、Signature 三個(gè)部分拼成一個(gè)字符串,每個(gè)部分之間用"點(diǎn)"(.)分隔,就可以返回給用戶
因?yàn)槭褂昧撕灻虼思词剐孤?,也無(wú)法被篡改
局限
- 服務(wù)器不保存Session信息,在沒(méi)有特殊邏輯的情況下,無(wú)法在使用過(guò)程中廢止某個(gè) token,也不能更改 token 的權(quán)限,一旦 JWT 簽發(fā)了,在到期之前就會(huì)始終有效
- Token本身就是認(rèn)證信息,一旦泄露,任何人都可以獲得該令牌的所有權(quán)限。為了減少盜用,JWT 的有效期應(yīng)該設(shè)置得比較短。對(duì)于一些比較重要的權(quán)限,使用時(shí)應(yīng)該再次對(duì)用戶進(jìn)行認(rèn)證
- 為了減少盜用,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸,要使用 HTTPS 協(xié)議傳輸
三、token授權(quán)之OAuth2.0
嚴(yán)格來(lái)講,OAuth2.0不算一種授權(quán)方式,而是一個(gè)安全的授權(quán)認(rèn)證的框架。為系統(tǒng)中不同角色、用戶、服務(wù)前端應(yīng)用(比如API),以及客戶端(比如網(wǎng)站或移動(dòng)App)提供了一套相互認(rèn)證的框架
所以一般而言,在OAuth2.0中存在三種角色:服務(wù)提供方,用戶,第三方服務(wù) ;用戶授權(quán)第三方服務(wù)使用自身的某些權(quán)限,去訪問(wèn)服務(wù)提供方的資源(比如用qq賬戶登錄微博)
OAuth2.0分為兩步,獲取Authorization以及獲取Token
獲取Authorization
- 用戶在授權(quán)界面,選擇需要授權(quán)的權(quán)限點(diǎn),登錄確定授權(quán)
- 授權(quán)后回調(diào)第三方服務(wù)的回調(diào)地址
- 通過(guò)回調(diào)地址,發(fā)送Authorization(可以看做是驗(yàn)證碼,有效期不長(zhǎng))給第三方服務(wù)
獲取Token并維護(hù)Token有效性
- 通過(guò)上面拿到的Authorization調(diào)用服務(wù)提供方的接口獲取token
- token由access token與refresh token兩個(gè)token組成,access token有效性比refresh token短
- 訪問(wèn)服務(wù)提供方接口需要使用access token,而當(dāng)access token快過(guò)期的時(shí)候就需要用refresh token請(qǐng)求token刷新接口,獲取新的token
OAuth 2.0 rfc文檔:https://www.rfc-editor.org/rfc/rfc6749
OAuth2.0提供了4種認(rèn)證方式,上面是最為復(fù)雜的一種,授權(quán)碼模式,其余3種授權(quán)方式如下
簡(jiǎn)化模式
不通過(guò)第三方應(yīng)用程序的服務(wù)器,直接在瀏覽器中向認(rèn)證服務(wù)器申請(qǐng)令牌,跳過(guò)了"授權(quán)碼"這個(gè)步驟。所有步驟在瀏覽器中完成,令牌對(duì)訪問(wèn)者是可見的,且客戶端不需要認(rèn)證
(A)客戶端將用戶導(dǎo)向認(rèn)證服務(wù)器。
(B)用戶決定是否給于客戶端授權(quán)。
(C)假設(shè)用戶給予授權(quán),認(rèn)證服務(wù)器將用戶導(dǎo)向客戶端指定的"重定向URI",并在URI的Hash部分包含了訪問(wèn)令牌。
(D)瀏覽器向資源服務(wù)器發(fā)出請(qǐng)求,其中不包括上一步收到的Hash值。
(E)資源服務(wù)器返回一個(gè)網(wǎng)頁(yè),其中包含的代碼可以獲取Hash值中的令牌。
(F)瀏覽器執(zhí)行上一步獲得的腳本,提取出令牌。
(G)瀏覽器將令牌發(fā)給客戶端。
密碼模式
用戶向客戶端提供自己的用戶名和密碼。客戶端使用這些信息,向"服務(wù)商提供商"索要授權(quán)。
在這種模式中,用戶必須把自己的密碼給客戶端,但是客戶端不得儲(chǔ)存密碼。這通常用在用戶對(duì)客戶端高度信任的情況下,比如客戶端是操作系統(tǒng)的一部分,或者由一個(gè)著名公司出品。而認(rèn)證服務(wù)器只有在其他授權(quán)模式無(wú)法執(zhí)行的情況下,才能考慮使用這種模式
(A)用戶向客戶端提供用戶名和密碼。
(B)客戶端將用戶名和密碼發(fā)給認(rèn)證服務(wù)器,向后者請(qǐng)求令牌。
(C)認(rèn)證服務(wù)器確認(rèn)無(wú)誤后,向客戶端提供訪問(wèn)令牌。
客戶端模式
指客戶端以自己的名義,而不是以用戶的名義,向"服務(wù)提供商"進(jìn)行認(rèn)證文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-775875.html
(A)客戶端向認(rèn)證服務(wù)器進(jìn)行身份認(rèn)證,并要求一個(gè)訪問(wèn)令牌。
(B)認(rèn)證服務(wù)器確認(rèn)無(wú)誤后,向客戶端提供訪問(wèn)令牌。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-775875.html
優(yōu)點(diǎn)
- 更安全,客戶端不接觸用戶密碼
- 資源服務(wù)器可以和授權(quán)服務(wù)器解耦
- 適用多種客戶端架構(gòu)場(chǎng)景
缺點(diǎn)
- 協(xié)議框架太寬泛,每個(gè)服務(wù)又都自己的實(shí)現(xiàn),兼容性和互操作性比較差
- 客戶端需要維護(hù)token有效性,維護(hù)定時(shí)刷新token任務(wù)
四、ak/sk認(rèn)證鑒權(quán)
- 服務(wù)提供方需要給每個(gè)用戶分配一對(duì) Access Key Id(AK) / Secret Access Key(SK)
- 雙方約定同樣的加密算法,利用 時(shí)間戳,sk,nonce(一個(gè)隨機(jī)值,為了避免請(qǐng)求重放),參數(shù)等信息作為計(jì)算因子,算出sign簽名
- 用戶在調(diào)用api時(shí),需要提供自己的身份認(rèn)證(AK),時(shí)間戳、nonce以及加密好的sign簽名
- 服務(wù)提供方驗(yàn)證簽名是否過(guò)期,驗(yàn)證nonce是否唯一,并利用同樣的算法算出sign,與傳入sign進(jìn)行比對(duì),如果一致則通過(guò)認(rèn)證
優(yōu)點(diǎn)
- 安全性高,在秘鑰與算法不泄露情況下,簽名無(wú)法破解
- 有過(guò)期時(shí)間,可以避免簽名長(zhǎng)期有效的情況
- 有防止重放機(jī)制,即使簽名被捕獲,也無(wú)法再次利用相同的簽名進(jìn)行請(qǐng)求
缺點(diǎn)
- 對(duì)于服務(wù)調(diào)用方與被調(diào)用方都需要一定的編碼要求
- 每次請(qǐng)求都需要重新計(jì)算簽名,不那么輕量
- 服務(wù)提供方需要維護(hù)ak/sk關(guān)系,并且需要維護(hù)nonce是否唯一邏輯
到了這里,關(guān)于Web API接口鑒權(quán)方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!