后端項(xiàng)目地址就不剝離開了碾篡,自己解讀(中間件那)
前端項(xiàng)目地址(可能是空的铡羡,為還沒上傳O(∩_∩)O哈哈~)
前言
Hello World拭嫁!怕是大多數(shù)程序員寫的第一句代碼了吧。我就是用C語言寫的第一個(gè)代碼就是它了浮入。雖然現(xiàn)在沒有從事有關(guān)C語言的工作龙优,不過還是受益于學(xué)習(xí)它所經(jīng)歷的每一行代碼。
登錄注冊怕是寫web應(yīng)用里的Hello World事秀!級存在了彤断。第一份工作做的是j2ee和app,做的第一個(gè)模塊就算是它了易迹。不過這個(gè)"Hello World!"可一點(diǎn)都不簡單宰衙。
正文
首先我們先搞清楚什么是認(rèn)證和授權(quán)。百度一下發(fā)現(xiàn)很掉書袋睹欲。其實(shí)吧簡單來說就是:認(rèn)證就是讓服務(wù)器知道你是誰供炼,授權(quán)就是服務(wù)器讓你知道你什么能干,什么不能干
認(rèn)證授權(quán)倆種方式:Session-Cookie與JWT
Session
服務(wù)器只有一臺(tái)窘疮,客戶端卻有千千萬袋哼。怎么能夠讓服務(wù)器知道當(dāng)前請求服務(wù)的是哪臺(tái)客戶端呢?我們舉個(gè)生活中的例子:
你去圖書館(服務(wù)端)借書(請求服務(wù))闸衫。先得辦卡(登錄獲取session_id)吧涛贯,放兜里(cookie)。去刷卡處刷卡看看卡是不是偽造的蔚出,看看卡里的信息和數(shù)據(jù)庫比對下看看有沒有過期等等(檢查session_id是否被篡改弟翘,是否失效根據(jù)session_id查詢下內(nèi)存或者數(shù)據(jù)庫(通常是內(nèi)存數(shù)據(jù)庫)里對應(yīng)的有沒有過期)。過期不給進(jìn)重新辦卡(重新登錄認(rèn)證)骄酗,沒過期就給進(jìn)(返回你請求的結(jié)果)
所以咯流程就是這樣子:
當(dāng) client通過用戶名密碼請求server并通過身份認(rèn)證后稀余,server就會(huì)生成身份認(rèn)證相關(guān)的 session 數(shù)據(jù),并且保存在內(nèi)存或者內(nèi)存數(shù)據(jù)庫酥筝。并將對應(yīng)的 sesssion_id返回給client滚躯,client會(huì)把保存session_id(可以加密簽名下防止篡改)在cookie雏门。此后client的所有請求都會(huì)附帶該session_id(畢竟默認(rèn)會(huì)把cookie傳給server)嘿歌,以確定server是否存在對應(yīng)的session數(shù)據(jù)以及檢驗(yàn)登錄狀態(tài)掸掏,權(quán)限啦巴拉巴拉......如果通過校驗(yàn)就該干嘛干嘛,否則重新登錄咯宙帝。
前端退出的話就清cookie丧凤。后端強(qiáng)制前端重新認(rèn)證的話就清或者修改session。
JWT
這里就不介紹jwt的三部分組成步脓、由什么組成愿待、怎么生成加密了。
日常的舉個(gè)生活中的例子吧:
你去游樂園(服務(wù)端)玩耍(請求服務(wù))靴患。先得買門票(登錄獲取token)吧仍侥,放兜里(cookie、header......)鸳君。去檢票口檢票看看票有沒有過期(檢查token是否失效)农渊。過期不給進(jìn)重新買票(重新登錄認(rèn)證),沒過期就給進(jìn)(返回你請求的結(jié)果)
有沒有覺得和Session有什么不一樣或颊?server不用存儲(chǔ)信息了砸紊。一切都存在客戶端。個(gè)人覺得這就是最大的不同囱挑。
這里大致列下倆者區(qū)別醉顽,一些比如JWT更簡單、APP對支持不易的一些已經(jīng)解決或者細(xì)究覺得很扯的或者大同小異的不在此列
Session | JWT | |
---|---|---|
安全性 | 得考慮CSRF攻擊 | 無需考慮 |
存儲(chǔ) | 需要倆端都存儲(chǔ) | 客戶端存儲(chǔ)即可 |
可控性 | 服務(wù)端可隨時(shí)修改權(quán)限.... | 只能等待Token過期 |
本來網(wǎng)上還是有很多區(qū)別的平挑,但是我想了下貌似就這么幾點(diǎn)游添。
安全性
首先這個(gè)還真不算什么。現(xiàn)在WEB框架該都內(nèi)置了防CSRF弹惦。而且既然知道有這個(gè)編寫代碼注意下也是應(yīng)該的否淤。
存儲(chǔ)
這個(gè)還真是,JWT真心可以棠隐,不過得看情況石抡。如果考慮可控性,那你簡直想哭助泽。
可控性
服務(wù)端存儲(chǔ)認(rèn)證相關(guān)信息還是很有必要的啰扛。舉個(gè)栗子。如果你發(fā)現(xiàn)你賬號(hào)被異地登錄嗡贺,你肯定想著換密碼呀隐解。換了以后發(fā)現(xiàn)我去,怎么又被異地登錄诫睬。因?yàn)門oken未過期煞茫,人家還是可以使用。這就很麻煩了。服務(wù)端根本不能控制续徽。這時(shí)候你會(huì)記得session得好蚓曼。
其他
還真沒什么好說的,可能有人覺得JWT加密解密開銷大钦扭、有人覺得JWT太長占空間纫版、session太老了該讓位了、JWT只需要存儲(chǔ)Token在客戶端方便客情、JWT加密感覺好安全不一而足......
對于以上的看別人博文沒什么卵用其弊,自己實(shí)現(xiàn)下就知道厲害了。
JWT變異之路(實(shí)現(xiàn))
實(shí)現(xiàn)來講的話有點(diǎn)后端開發(fā)基礎(chǔ)的應(yīng)該都知道怎么寫代碼在知道實(shí)現(xiàn)原理的情況下膀斋。這里不再講述梭伐,要講的是本人使用JWT用于個(gè)人博客遇到一些情況。在此記錄仰担,與君共勉之籽御。
前提
首先輕輕松松實(shí)現(xiàn)了JWT。本人后端采用Koa2搭建惰匙。鑒權(quán)使用koa-jwt技掏、生成token采用jsonwebtoken。npm就是這么方便啊项鬼。不過還是懷念當(dāng)初馳騁j2ee的時(shí)候哑梳。言歸正傳。發(fā)現(xiàn)幾個(gè)個(gè)很蛋疼的問題绘盟。
遇到的問題
- 我什么服務(wù)端居然不能掌控全局鸠真,居然不能讓禁止某個(gè)用戶登錄。這哪能忍龄毡。
好吧吠卷,絞盡腦汁鸣奔,超越處女座忍受極限柒莉。我生成token返回前端時(shí),將用戶id作為key忘古,token作為value(存token只是隨意路操,這里只是舉例)存在redis疾渴,且設(shè)置過期時(shí)間和token一致。每次前端請求時(shí)我都先和往常一般常規(guī)驗(yàn)證屯仗,ok之后繼續(xù)解出用戶id搞坝,查看redis有沒有這條記錄。有的話該干嘛干嘛魁袜,沒有的話說明因?yàn)槟撤N原因你被管理員kill掉了桩撮。乖乖重新登錄或者申訴吧敦第。
感覺還可以,雖然不再是無狀態(tài)了店量,但是解決了問題不是申尼,心里好受多了。但是發(fā)現(xiàn)想多了垫桂。
- 這點(diǎn)其實(shí)是因?yàn)楣ぷ髁ⅠR就想到了。當(dāng)時(shí)公司要開發(fā)個(gè)聯(lián)機(jī)幫助工具粟按。就交給我全權(quán)開發(fā)诬滩。
當(dāng)時(shí)開發(fā)完了有人反饋說是我寫到一半有點(diǎn)事耽擱了下,然后退出了灭将,這個(gè)不就白寫了疼鸟。好吧,想起自己的個(gè)人博客庙曙,雖然我肯定會(huì)做個(gè)keyup監(jiān)測保存功能空镜,但是有可能我訪問著訪問著就退出了。用戶體驗(yàn)有木有啊捌朴。辣雞有木有啊吴攒。
那就客戶端加個(gè)刷新token策略咯。綜合考慮之下打算認(rèn)證時(shí)后端生成返回倆個(gè)token給前端:accesstoken砂蔽、refreshtoken洼怔。前者用于訪問鑒權(quán),后者用于刷新token左驾。區(qū)別在于前者過期時(shí)間短镣隶,后者過期時(shí)間長。具體時(shí)長自己開心就好诡右。
然后現(xiàn)在就這樣子了安岂。比如我accesstoken過期時(shí)間30min,refreshtoken過期時(shí)間7d帆吻。在即將過期的時(shí)候(25min)域那,我使用refreshtoken重新向服務(wù)端拉取新的accesstoken。你想順帶更新下refreshtoken也是可以的猜煮×瘀ǎ看自己業(yè)務(wù)邏輯使用場景。當(dāng)然也可以在過期時(shí)檢測下refreshtoken有沒有過期友瘤,沒過期的話拉下新token翠肘。
以上就是本人遇到的倆個(gè)問題,結(jié)果最后發(fā)現(xiàn)我的JWT又變成Session辫秧。
后記
看的再多不如動(dòng)手一次束倍。因?yàn)闀?huì)發(fā)現(xiàn)想象著很簡單的東西實(shí)現(xiàn)起來完全脫離自己掌控。