- 1.對于敏感的api接口,需使用https協(xié)議
https是在http超文本傳輸協(xié)議加入SSL層跨嘉,它在網(wǎng)絡(luò)間通信是加密的川慌,所以需要加密證書
- 2.簽名的設(shè)計
原理: 用戶登錄后向服務(wù)器提供用戶認證信息(如賬戶和密碼),服務(wù)器認證完后給客戶端返回一個Token令牌,用戶再次獲取信息時梦重,帶上此令牌兑燥,如果令牌正取,則返回數(shù)據(jù)琴拧。對于獲取Token信息后降瞳,訪問用戶相關(guān)接口,客戶端請求的url需要帶上如下參數(shù):
時間戳: timestamp
Token令牌: token
然后將所有用戶請求的參數(shù)按照字母排序(包括timestamp蚓胸,token)挣饥,然后更具MD5加密(可以加點鹽),全部大寫沛膳,生成sign簽名扔枫,這就是 所說的url簽名算法。然后登陸后每次調(diào)用用戶信息時锹安,帶上sign茧吊,timestamp,token參數(shù)
加上時間戳和token:https://www.andy.cn/api/user/update/info.shtml?city=北京×tamp=12445323134&token=wefkfjdskfjewfjkjfdfnc
最終的請求如:https://www.andy.cn /api/user/update/info.shtml?city=北京×tamp=12445323134& token=wefkfjdskfjewfjkjfdfnc&sign=FDK2434JKJFD334FDF2
其最終的原理是減小明文的暴露次數(shù)八毯;保證數(shù)據(jù)安全的訪問
具體實現(xiàn)如下:
1>api請求客戶端向服務(wù)器端一次發(fā)送用用戶認證信息(用戶名和密碼)搓侄,服務(wù)器端請求到改請求后,驗證用戶信息是否正確
如果正確:則返回一個唯一不重復(fù)的字符串(一般為UUID)话速,然后在Redis(任意緩存服務(wù)器)中維護Token----Uid的用戶信息關(guān)系讶踪,以便其他api對token的校驗。
2>服務(wù)器設(shè)計一個url請求攔截規(guī)則
(1) 判斷是否包含timestamp泊交,token乳讥,sign參數(shù),如果不含有返回錯誤碼廓俭。
(2)判斷服務(wù)器接到請求的時間和參數(shù)中的時間戳是否相差很長一段時間(時間自定義如半個小時)云石,如果超過則說明該 url已經(jīng)過期(如果url被盜,他改變了時間戳研乒,但是會導(dǎo)致sign簽名不相等)汹忠。
(3)判斷token是否有效,根據(jù)請求過來的token雹熬,查詢redis緩存中的uid宽菜,如果獲取不到這說明該token已過期。
(4)根據(jù)用戶請求的url參數(shù)竿报,服務(wù)器端按照同樣的規(guī)則生成sign簽名铅乡,對比簽名看是否相等,相等則放行烈菌。(自然url簽名 也無法100%保證其安全阵幸,也可以通過公鑰AES對數(shù)據(jù)和url加密花履,但這樣如果無法確保公鑰丟失,所以簽名只是很大程 度上保證安全)挚赊。
(5)此url攔截只需對獲取身份認證的url放行(如登陸url)臭挽,剩余所有的url都需攔截
3.Token和Uid關(guān)系維護
對于用戶登錄我們需要創(chuàng)建token--uid的關(guān)系,用戶退出時需要需刪除token--uid的關(guān)系
簽名實現(xiàn):
1.獲取全部請求參數(shù)
String sign = request.getParameter("sign");
Enumeration<?> pNames = request.getParameterNames();
Map<String, Object> params = new HashMap<String, Object>();
while (pNames.hasMoreElements()) {
String pName = (String) pNames.nextElement();
if("sign".equals(pName))continue;
Object pValue = request.getParameter(pName);
params.put(pName, pValue);
}
2.生成簽名
public static String createSign(Map<String, String> params, boolean encode)
throws UnsupportedEncodingException {
Set<String> keysSet = params.keySet();
Object[] keys = keysSet.toArray();
Arrays.sort(keys);
StringBuffer temp = new StringBuffer();
boolean first = true;
for (Object key : keys) {
if (first) {
first = false;
} else {
temp.append("&");
}
temp.append(key).append("=");
Object value = params.get(key);
String valueString = "";
if (null != value) {
valueString = String.valueOf(value);
}
if (encode) {
temp.append(URLEncoder.encode(valueString, "UTF-8"));
} else {
temp.append(valueString);
}
}
return MD5Utils.getMD5(temp.toString()).toUpperCase();
}
-
SpringSecurity + JWT 實現(xiàn)單點登陸
1.什么是單點登陸
單點登錄(Single Sign On)咬腕,簡稱為 SSO欢峰,是目前比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一。SSO的定義是在多個應(yīng)用系統(tǒng)中涨共,用戶只需要登錄一次就可以訪問所有相互信任的應(yīng)用系統(tǒng)
2.簡單的運行機制
單點登錄的機制其實是比較簡單的纽帖,用一個現(xiàn)實中的例子做比較。某公園內(nèi)部有許多獨立的景點举反,游客可以在各個景點門口單獨買票懊直。
對于需要游玩所有的景點的游客,這種買票方式很不方便火鼻,需要在每個景點門口排隊買票室囊,錢包拿 進拿出的,容易丟失魁索,很不安全融撞。
于是絕大多數(shù)游客選擇在大門口買一張通票(也叫套票),就可以玩遍所有的景點而不需要重新再買票粗蔚。他們只需要在每個景點門 口出示一下剛才買的套票就能夠被允許進入每個獨立的景點尝偎。
單點登錄的機制也一樣,如下圖所示鹏控,
image.png
用戶認證
:這一環(huán)節(jié)主要是用戶向認證服務(wù)器發(fā)起認證請求致扯,認證服務(wù)器給用戶返回一個成功的令牌token,主要在認證服務(wù)器中完成当辐,即圖中的認證系統(tǒng)抖僵,注意認證系統(tǒng)只能有一個
身份校驗
: 這一環(huán)節(jié)是用戶攜帶token去訪問其他服務(wù)器時,在其他服務(wù)器中要對token的真?zhèn)芜M行檢驗缘揪,主要在資源服務(wù)器中完成耍群,即圖中的應(yīng)用系統(tǒng)2 3
3.
JWT
介紹
概念說明
從分布式認證流程中,我們不難發(fā)現(xiàn)寺晌,這中間起最關(guān)鍵作用的就是token世吨,token的安全與否澡刹,直接關(guān)系到系統(tǒng)的健壯性呻征,這里我們選擇使用JWT來實現(xiàn)token的生成和校驗。
JWT
罢浇,全稱JSON Web Token
陆赋,官網(wǎng)地址https://jwt.io沐祷,是一款出色的分布式身份校驗方案≡艿海可以生成token赖临,也可以解析檢驗token。
JWT生成的token由三部分組成:
頭部
:主要設(shè)置一些規(guī)范信息灾锯,簽名部分的編碼格式就在頭部中聲明兢榨。載荷
:token中存放有效信息的部分,比如用戶名顺饮,用戶角色吵聪,過期時間等,但是不要放密碼兼雄,會泄露吟逝!簽名
:將頭部與載荷分別采用base64編碼后,用“.”相連赦肋,再加入鹽块攒,最后使用頭部聲明的編碼類型進行編碼,就得到了簽名佃乘。
JWT
生成token的安全性分析
從JWT生成的token組成上來看囱井,要想避免token被偽造,主要就得看簽名部分了趣避,而簽名部分又有三部分組成琅绅,其中頭部和載荷的base64編碼,幾乎是透明的鹅巍,毫無安全性可言千扶,那么最終守護token安全的重擔(dān)就落在了加入的鹽上面了!
試想:如果生成token所用的鹽與解析token時加入的鹽是一樣的骆捧。豈不是類似于中國人民銀行把人民幣防偽技術(shù)公開了澎羞?大家可以用這個鹽來解析token,就能用來偽造token敛苇。這時妆绞,我們就需要對鹽采用非對稱加密的方式進行加密,以達到生成token與校驗token方所用的鹽不一致的安全效果枫攀!
非對稱加密RSA
介紹:
基本原理:同時生成兩把密鑰:私鑰
和公鑰
括饶,私鑰隱秘保存,公鑰可以下發(fā)給信任客戶端
私鑰加密
来涨,持有私鑰或公鑰才可以解密
公鑰加密
图焰,持有私鑰才可解密
優(yōu)點: 安全,難以破解
缺點: 算法比較耗時蹦掐,為了安全技羔,可以接受
歷史: 三位數(shù)學(xué)家Rivest僵闯、Shamir 和 Adleman 設(shè)計了一種算法,可以實現(xiàn)非對稱加密藤滥。這種算法用他們?nèi)齻€人的名字縮寫:RSA
鳖粟。
4.
SpringSecurity
整合JWT
- 4.1 認證思路分析
SpringSecurity
主要是通過過濾器來實現(xiàn)功能的!我們要找到SpringSecurity實現(xiàn)認證和校驗身份的過濾器
4.2 分析分布式認證流程
用戶認證
:
由于分布式項目拙绊,多數(shù)是前后端分離的架構(gòu)設(shè)計向图,我們要滿足可以接受異步post的認證請求參數(shù),需要修改UsernamePasswordAuthenticationFilter過濾器中attemptAuthentication方法标沪,讓其能夠接收請求體张漂。
另外,默認successfulAuthentication方法在認證通過后谨娜,是把用戶信息直接放入session就完事了航攒,現(xiàn)在我們需要修改這個方法,在認證通過后生成token并返回給用戶趴梢。
身份校驗
:
原來BasicAuthenticationFilter過濾器中doFilterInternal方法校驗用戶是否登錄漠畜,就是看session中是否有用戶信息,我們要修改為坞靶,驗證用戶攜帶的token是否合法憔狞,并解析出用戶信息,交給SpringSecurity彰阴,以便于后續(xù)的授權(quán)功能可以正常使用
參考文章:
https://mp.weixin.qq.com/s?__biz=Mzg2MjEwMjI1Mg==&mid=2247516734&idx=1&sn=966d166d3052f10b9310ff4014733669&chksm=ce0e35bdf979bcabbb75366e1bad32bdbf8f41d1dc80b8be6e39225bd708913ce2c93472f2fc&mpshare=1&scene=23&srcid=0602G1Eh5izWvt4jbaX9a81P&sharer_sharetime=1622628809523&sharer_shareid=f770d25bc57f1c2f9159f85750f854dc#rd