在現(xiàn)代web開發(fā)中,系統(tǒng)鑒權(quán)服務(wù)已是基本標(biāo)配模塊,有些開發(fā)框架甚至內(nèi)置了鑒權(quán)模塊的實(shí)現(xiàn),或者提供一些鑒權(quán)的工具類,然而鑒權(quán)的方式也分為多種,了解各種鑒權(quán)方式的特點(diǎn)及使用場(chǎng)景可以幫助我們構(gòu)建更健壯的web系統(tǒng)。以下列出四種常見的鑒權(quán)方式,我們來(lái)認(rèn)識(shí)一下:

創(chuàng)新互聯(lián)長(zhǎng)期為成百上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為祿豐企業(yè)提供專業(yè)的成都網(wǎng)站制作、網(wǎng)站建設(shè),祿豐網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
HTTP 基本身份驗(yàn)證,允許客戶端在標(biāo)準(zhǔn)的 HTTP 頭中發(fā)送用戶名和密碼。服務(wù)端可以驗(yàn)證這些信息,并確認(rèn)客戶端是否有權(quán)訪問(wèn)服務(wù)。這樣做的好處在于,這是一種非常容易理解且得到廣泛支持的協(xié)議。問(wèn)題在于,通過(guò) HTTP 有很高的風(fēng)險(xiǎn),因?yàn)橛脩裘兔艽a并沒(méi)有以安全的方式發(fā)送。任何中間方都可以看到 HTTP 頭的信息并讀取里面的數(shù)據(jù)。因此,HTTP 基本身份驗(yàn)證通常應(yīng)該通過(guò) HTTPS 進(jìn)行通信。
當(dāng)使用 HTTPS 時(shí),客戶端獲得強(qiáng)有力的保證,它所通信的服務(wù)端就是客戶端想要通信的服務(wù)端。它給予我們額外的保護(hù),避免人們竊聽客戶端和服務(wù)端之間的通信,或篡改有效負(fù)載。
服務(wù)端需要管理自己的SSL證書,當(dāng)需要管理多臺(tái)機(jī)器時(shí)會(huì)出現(xiàn)問(wèn)題。一些組織自己承擔(dān)簽發(fā)證書的過(guò)程,這是一個(gè)額外的行政和運(yùn)營(yíng)負(fù)擔(dān)。管理這方面的自動(dòng)化工具遠(yuǎn)不夠成熟,使用它們后你會(huì)發(fā)現(xiàn),需要自己處理的事情就不止證書簽發(fā)了。自簽名證書不容易撤銷,因此需要對(duì)災(zāi)難情景有更多的考慮。看看你是否能夠避免自簽名,以避開所有的這些工作。
SSL 之上的流量不能被反向代理服務(wù)器(比如 Varnish 或 Squid)所緩存,這是使用 HTTPS 的另一個(gè)缺點(diǎn)。這意味著,如果你需要緩存信息,就不得不在服務(wù)端或客戶端內(nèi)部實(shí)現(xiàn)。你可以在負(fù)載均衡中把 Https 的請(qǐng)求轉(zhuǎn)成 Http 的請(qǐng)求,然后在負(fù)載均衡之后就可以使用緩存了。
還需要考慮,如果我們已經(jīng)在使用現(xiàn)成的 SSO 方案(比如包含用戶名密碼信息的 SAML),該怎么辦。我們想要基本身份驗(yàn)證使用同一套認(rèn)證信息,然后在同一個(gè)進(jìn)程里頒發(fā)和撤銷嗎?讓服務(wù)與實(shí)現(xiàn) SSO 所使用的那個(gè)目錄服務(wù)進(jìn)行通信即可做到這一點(diǎn)。或者,我們可以在服務(wù)內(nèi)部存儲(chǔ)用戶名和密碼,但需要承擔(dān)存在重復(fù)行為的風(fēng)險(xiǎn)。
注意:使用這種方法,服務(wù)器只知道客戶端有用戶名和密碼。我們不知道這個(gè)信息是否來(lái)自我們期望的機(jī)器;它可能來(lái)自網(wǎng)絡(luò)中的其他人。
HTTP 基本身份驗(yàn)證是一種簡(jiǎn)單但不那么安全的認(rèn)證方式,不太建議用于公開的商業(yè)應(yīng)用,在此便不再展開,我們關(guān)注以下幾種認(rèn)證方式。
http協(xié)議是一種無(wú)狀態(tài)的協(xié)議,如果沒(méi)有任何認(rèn)證機(jī)制,服務(wù)端對(duì)任何客戶端的請(qǐng)求都是無(wú)差別的。在Web2.0時(shí)代,為了加強(qiáng)B/S交互的安全性,衍生出了Session-Cookie鑒權(quán)機(jī)制,通過(guò)在服務(wù)端開啟會(huì)話,客戶端存儲(chǔ)SessionID,在每次請(qǐng)求時(shí)通過(guò)cookie傳輸SessionID的形式實(shí)現(xiàn)服務(wù)端基本鑒權(quán)。
cookie是保存在本地終端的數(shù)據(jù)。cookie由服務(wù)器生成,發(fā)送給瀏覽器,瀏覽器把cookie以kv形式保存到某個(gè)目錄下的文本文件內(nèi),下一次請(qǐng)求同一網(wǎng)站時(shí)會(huì)把該cookie發(fā)送給服務(wù)器。由于cookie是存在客戶端上的,所以瀏覽器加入了一些限制確保cookie不會(huì)被惡意使用,同時(shí)不會(huì)占據(jù)太多磁盤空間,所以每個(gè)域的cookie數(shù)量是有限的。
cookie的組成有:名稱(key)、值(value)、有效域(domain)、路徑(域的路徑,一般設(shè)置為全局:"")、失效時(shí)間、安全標(biāo)志(指定后,cookie只有在使用SSL連接時(shí)才發(fā)送到服務(wù)器(https))。
Session的中文翻譯是“會(huì)話”,當(dāng)用戶打開某個(gè)web應(yīng)用時(shí),便與web服務(wù)器產(chǎn)生一次session。服務(wù)器使用session把用戶的信息臨時(shí)保存在了服務(wù)器上,用戶離開網(wǎng)站后session會(huì)被銷毀。這種用戶信息存儲(chǔ)方式相對(duì)cookie來(lái)說(shuō)更安全,可是session有一個(gè)缺陷:如果web服務(wù)器做了負(fù)載均衡,那么下一個(gè)操作請(qǐng)求到了另一臺(tái)服務(wù)器的時(shí)候session會(huì)丟失。
當(dāng)程序需要為某個(gè)客戶端的請(qǐng)求創(chuàng)建一個(gè)session時(shí),服務(wù)器首先檢查這個(gè)客戶端的請(qǐng)求里是否已包含了一個(gè)session標(biāo)識(shí)(稱為SessionID),如果已包含則說(shuō)明以前已經(jīng)為此客戶端創(chuàng)建過(guò)Session,服務(wù)器就按照SessionID把這個(gè)Session檢索出來(lái)使用(檢索不到,會(huì)新建一個(gè)),如果客戶端請(qǐng)求不包含SessionID,則為此客戶端創(chuàng)建一個(gè)Session并且生成一個(gè)與此Session相關(guān)聯(lián)的SessionID,SessionID的值應(yīng)該是一個(gè)既不會(huì)重復(fù),又不容易被找到規(guī)律以仿造的字符串,這個(gè)SessionID將被在本次響應(yīng)中返回給客戶端保存。
保存這個(gè)SessionID的方式可以采用Cookie,這樣在交互過(guò)程中瀏覽器可以自動(dòng)的按照規(guī)則把這個(gè)標(biāo)識(shí)發(fā)揮給服務(wù)器。一般這個(gè)Cookie的名字都是類似于SEEESIONID。但Cookie可以被人為的禁止,則必須有其他機(jī)制以便在Cookie被禁止時(shí)仍然能夠把SessionID傳遞回服務(wù)器。
客戶端第一次發(fā)送請(qǐng)求給服務(wù)器,此時(shí)服務(wù)器啟動(dòng)Session會(huì)話,產(chǎn)生一個(gè)唯一的SessionID,并通過(guò)Response的SetCookie返回給客戶端,保存于客戶端(一般為瀏覽器),并與一個(gè)瀏覽器窗口對(duì)應(yīng)著,由于HTTP協(xié)議的特性,這一次Request-Response
后連接就斷開了。以后此客戶端再發(fā)送請(qǐng)求給服務(wù)器的時(shí)候,就會(huì)在請(qǐng)求Request頭中攜帶cookie,由于cookie中帶有Key為sessionID的數(shù)據(jù),所以服務(wù)器就知道這是剛才那個(gè)客戶端。
正如我們前面所討論的,如果擔(dān)心用戶名和密碼被泄露,HTTP基本身份驗(yàn)證使用普通 HTTP 并不是非常明智的。傳統(tǒng)的替代方式是使用HTTPS路由通信,但也有一些缺點(diǎn)。除了需要管理證書,HTTPS通信的開銷使得服務(wù)器壓力增加,而且通信難以被輕松地緩存。另外Session-Cookie機(jī)制也會(huì)有被客戶限制的隱患,如果用戶禁用Cookie則必須由其它方式實(shí)現(xiàn)鑒權(quán)。
所謂Token,即令牌。客戶端需要鑒權(quán)訪問(wèn)私人信息時(shí),會(huì)首次向服務(wù)端發(fā)送身份驗(yàn)證信息(如用戶名、密碼),服務(wù)端校驗(yàn)正確后會(huì)根據(jù)一定的加密算法生成Token令牌發(fā)放給客戶端,此后客戶端只需通過(guò)Token,服務(wù)端只需驗(yàn)證Token就可識(shí)別客戶并進(jìn)行交互,Token可存放于HTTP Header也可存放與Cookie。
以上為一個(gè)簡(jiǎn)單的Token鑒權(quán)過(guò)程。
關(guān)于Token機(jī)制,業(yè)界有一種叫JWT(JsonWebToken)的實(shí)現(xiàn)機(jī)制,下面我們來(lái)了解JWT。
JWT.io 對(duì)JSON Web Tokens進(jìn)行了很好的介紹,
國(guó)內(nèi)阮一峰的 《JSON Web Token 入門教程》 也講得非常好懂,可以出門右拐了解一下。
簡(jiǎn)而言之,它是一個(gè)簽名的JSON對(duì)象,可以執(zhí)行一些有用的操作(例如,身份驗(yàn)證)。它是一組字串,分Header(頭部)、Payload(負(fù)載)、Signature(簽名)三部分,由'.'號(hào)連接,看起來(lái)就像下面這樣:
用戶發(fā)送認(rèn)證信息給服務(wù)端后,服務(wù)端通過(guò)JWT生成規(guī)則,生成JWT字串作為Token發(fā)放給用戶,用戶以后每次訪問(wèn)都在HTTP Header攜帶JWT字串,已達(dá)到鑒權(quán)目的。由于其內(nèi)部攜帶用戶信息,部分使用者已經(jīng)發(fā)現(xiàn)其安全隱患,但其安全度不至于太過(guò)容易破解,在移動(dòng)應(yīng)用中的鑒權(quán)機(jī)制使用較多,除此之外,一些分布式的微服務(wù)應(yīng)用也通過(guò)JWT進(jìn)行模塊間的鑒權(quán),還是有一定的使用場(chǎng)景的。
Go開源社區(qū)已有比較成熟的JWT包實(shí)現(xiàn): jwt-go ,內(nèi)附有JWT編解碼的使用用例,還是很好懂的,感興趣的可get來(lái)使用。在另一篇中也做了Go 使用JWT鑒權(quán)的示例: 《Go 鑒權(quán)(三):JWT》 ,感興趣可閱讀以下,自己也在項(xiàng)目中實(shí)踐一下。
OAUTH協(xié)議為用戶資源的授權(quán)提供了一個(gè)安全的、開放而又簡(jiǎn)易的標(biāo)準(zhǔn)。同時(shí),任何第三方都可以使用OAUTH認(rèn)證服務(wù),任何服務(wù)提供商都可以實(shí)現(xiàn)自身的OAUTH認(rèn)證服務(wù),因而OAUTH是開放的。
OpenID Connect 是 OAuth 2.0 具體實(shí)現(xiàn)中的一個(gè)標(biāo)準(zhǔn)。它使用簡(jiǎn)單的 REST 調(diào)用,因?yàn)樘岣吡似湟子眯浴?duì)于一個(gè)面向公眾的網(wǎng)站,你或許可以使用Google、Facebook、Github等作為提供者,國(guó)內(nèi)可以使用QQ、微信、淘寶等作為提供者。但對(duì)于內(nèi)部系統(tǒng),或?qū)τ跀?shù)據(jù)需要有更多控制權(quán)的系統(tǒng)而言,你會(huì)希望有自己的內(nèi)部身份提供者。
OAuth2.0有四種授權(quán)模式,具體可看阮一峰的 《理解OAuth2.0》 ,其內(nèi)容非常詳細(xì)且好理解。
我們這里說(shuō)一下最完整的授權(quán)碼模式:
以上為OAuth2.0的認(rèn)證過(guò)程。
各大廠都有提供基于OAuth2.0的三方授權(quán)服務(wù),如QQ、微信、淘寶等等,有需要可移步到各自的開放平臺(tái)查看文檔,大都有提供Go的接口實(shí)現(xiàn);另你也可參考使用Go官方提供實(shí)現(xiàn)的包 ,里面包含多數(shù)熱門的OAuth客戶端。
推薦使用 這個(gè)開源項(xiàng)目,幫助你構(gòu)建自己的OAuth服務(wù)
網(wǎng)關(guān)=反向代理+負(fù)載均衡+各種策略,技術(shù)實(shí)現(xiàn)也有多種多樣,有基于 nginx 使用 lua 的實(shí)現(xiàn),比如 openresty、kong;也有基于 zuul 的通用網(wǎng)關(guān);還有就是 golang 的網(wǎng)關(guān),比如 tyk。
這篇文章主要是講如何基于 golang 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的網(wǎng)關(guān)。
轉(zhuǎn)自: troy.wang/docs/golang/posts/golang-gateway/
整理:go語(yǔ)言鐘文文檔:
啟動(dòng)兩個(gè)后端 web 服務(wù)(代碼)
這里使用命令行工具進(jìn)行測(cè)試
具體代碼
直接使用基礎(chǔ)庫(kù) httputil 提供的NewSingleHostReverseProxy即可,返回的reverseProxy對(duì)象實(shí)現(xiàn)了serveHttp方法,因此可以直接作為 handler。
具體代碼
director中定義回調(diào)函數(shù),入?yún)?http.Request,決定如何構(gòu)造向后端的請(qǐng)求,比如 host 是否向后傳遞,是否進(jìn)行 url 重寫,對(duì)于 header 的處理,后端 target 的選擇等,都可以在這里完成。
director在這里具體做了:
modifyResponse中定義回調(diào)函數(shù),入?yún)?http.Response,用于修改響應(yīng)的信息,比如響應(yīng)的 Body,響應(yīng)的 Header 等信息。
最終依舊是返回一個(gè)ReverseProxy,然后將這個(gè)對(duì)象作為 handler 傳入即可。
參考 2.2 中的NewSingleHostReverseProxy,只需要實(shí)現(xiàn)一個(gè)類似的、支持多 targets 的方法即可,具體實(shí)現(xiàn)見后面。
作為一個(gè)網(wǎng)關(guān)服務(wù),在上面 2.3 的基礎(chǔ)上,需要支持必要的負(fù)載均衡策略,比如:
隨便 random 一個(gè)整數(shù)作為索引,然后取對(duì)應(yīng)的地址即可,實(shí)現(xiàn)比較簡(jiǎn)單。
具體代碼
使用curIndex進(jìn)行累加計(jì)數(shù),一旦超過(guò) rss 數(shù)組的長(zhǎng)度,則重置。
具體代碼
輪詢帶權(quán)重,如果使用計(jì)數(shù)遞減的方式,如果權(quán)重是5,1,1那么后端 rs 依次為a,a,a,a,a,b,c,a,a,a,a…,其中 a 后端會(huì)瞬間壓力過(guò)大;參考 nginx 內(nèi)部的加權(quán)輪詢,或者應(yīng)該稱之為平滑加權(quán)輪詢,思路是:
后端真實(shí)節(jié)點(diǎn)包含三個(gè)權(quán)重:
操作步驟:
具體代碼
一致性 hash 算法,主要是用于分布式 cache 熱點(diǎn)/命中問(wèn)題;這里用于基于某 key 的 hash 值,路由到固定后端,但是只能是基本滿足流量綁定,一旦后端目標(biāo)節(jié)點(diǎn)故障,會(huì)自動(dòng)平移到環(huán)上最近的那么個(gè)節(jié)點(diǎn)。
實(shí)現(xiàn):
具體代碼
每一種不同的負(fù)載均衡算法,只需要實(shí)現(xiàn)添加以及獲取的接口即可。
然后使用工廠方法,根據(jù)傳入的參數(shù),決定使用哪種負(fù)載均衡策略。
具體代碼
作為網(wǎng)關(guān),中間件必不可少,這類包括請(qǐng)求響應(yīng)的模式,一般稱作洋蔥模式,每一層都是中間件,一層層進(jìn)去,然后一層層出來(lái)。
中間件的實(shí)現(xiàn)一般有兩種,一種是使用數(shù)組,然后配合 index 計(jì)數(shù);一種是鏈?zhǔn)秸{(diào)用。
具體代碼
這個(gè)庫(kù)已經(jīng)沒(méi)人維護(hù)了,他們現(xiàn)在新搞了一個(gè),具體可以去github上看
jwt(json web token)是一種用于前后端身份認(rèn)證的方法,一個(gè)jwt由header,payload,和signature組成。
1.Claims
claims是一個(gè)實(shí)現(xiàn)了Valid方法的interface,Valid方法用于判斷該claim是否合法
2.Keyfunc
Keyfunc在使用時(shí)一般都是返回secret密鑰,可以根據(jù)Token的種類不同返回不同的密鑰.
官方文檔:This allows you to use properties in the Header of the token (such as 'kid') to identify which key to use.
3.Mapclaims
一個(gè)用于放decode出來(lái)的claim的map,有Vaild和一系列VerifyXXX的方法
4.Parser
用來(lái)將tokenstr轉(zhuǎn)換成token
5.SigningMethod
簽名方法的接口,可以通過(guò)實(shí)現(xiàn)這個(gè)接口自定義簽名方法,jwt-go內(nèi)置一些實(shí)現(xiàn)了SigningMethod的結(jié)構(gòu)體
6.StandardClaims
jwt官方規(guī)定的一些預(yù)定義的payload:
7.Token
Token的結(jié)構(gòu)體
8.ValidationError
定義解析Token時(shí)遇到的一些錯(cuò)誤
首先我們先來(lái)看Parse()
實(shí)際上是調(diào)用了ParseWithClaims,第二個(gè)參數(shù)就是一個(gè)map[string]interface,這個(gè)函數(shù)的源碼如下,這個(gè)函數(shù)內(nèi)部調(diào)用的ParseUnverified,我們先來(lái)看看這個(gè)函數(shù)
官方的解釋是,這個(gè)函數(shù)不校驗(yàn)簽名的有效性,只單純負(fù)責(zé)把tokenStr變成Token對(duì)象,而之后的事情就是交給ParseWithClaims來(lái)做啦
可以看到,ParseUnverified這個(gè)方法真的只是單純的解碼Header段和Claim段,然后檢查一下用的alg是不是合法,就返回了,讓我們繼續(xù)往下看驗(yàn)證的邏輯
ok,關(guān)于解析token的主要方法我們已經(jīng)看完了,接下來(lái)我們來(lái)看看如何生成一個(gè)token,其實(shí)就是反著操作一遍
先看New函數(shù),選擇一種SigningMethod,新建一個(gè)token,內(nèi)部調(diào)用NewWithClaims
再看NewWithClaims,發(fā)現(xiàn)就是簡(jiǎn)單的給JwtToken的三個(gè)部分賦值
最后是SignedString,即使用alg的算法給token加密,生成最終的tokenStr,內(nèi)部調(diào)用了SigningString,所以先看SigningString
發(fā)現(xiàn)SigningString就是把token的頭部先變成json然后base64url編碼,但是沒(méi)有生成jwtToken的最后一個(gè)部分
所以SignedString作用就是用給定的加密方法和你的SecretKey對(duì)前面兩部分加密,添在token的最后一段,至此token生成完畢
分享題目:go語(yǔ)言配合jwt go 語(yǔ)言
文章URL:http://www.chinadenli.net/article46/dooephg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷、標(biāo)簽優(yōu)化、網(wǎng)站導(dǎo)航、企業(yè)網(wǎng)站制作、響應(yīng)式網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)