Http協(xié)議是無(wú)狀態(tài)的,一次請(qǐng)求結(jié)束,連接斷開,下次服務(wù)器再收到請(qǐng)求,它就不知道這個(gè)請(qǐng)求是哪個(gè)用戶發(fā)過(guò)來(lái)的。但是對(duì)我們的應(yīng)用而言,它是需要有狀態(tài)管理的,以便服務(wù)端能夠準(zhǔn)確的知道Http請(qǐng)求是哪個(gè)用戶發(fā)起的,從而判斷他是否有權(quán)限繼續(xù)這個(gè)請(qǐng)求。這個(gè)過(guò)程就是常說(shuō)的會(huì)話管理。
本文總結(jié)了3種常見的實(shí)現(xiàn)web應(yīng)用會(huì)話管理的方式:
- 基于session
- 基于公鑰/私鑰
- 基于token
一、基于Session
Session就不用多說(shuō)了,至于分布式Session實(shí)現(xiàn)方案 Java中通過(guò)Spring Session可以很方便的實(shí)現(xiàn)分布式Session管理。
二、基于公鑰/私鑰
事先給客戶端分配一個(gè)app_id和app_secret,客戶端調(diào)用接口的時(shí)候?qū)I(yè)務(wù)參數(shù)按字母排序,首尾加app_secret再RSA2(推薦使用SHA256,MD5和SHA1已被攻破)生成前面sign,然后再將業(yè)務(wù)參數(shù)和sign發(fā)送給服務(wù)器,服務(wù)器端用相同的方式生成sign,如果sign相等則路由到業(yè)務(wù)方法,否則返回鑒權(quán)失敗。
示例代碼如下:
private static final String UTF_8 = "UTF-8";
public static String encode(Map<String, String> param, String secret, boolean encode) {
Set<String> keysSet = param.keySet();
Object[] keys = keysSet.toArray();
Arrays.sort(keys); //按參數(shù)名字典順序排序
StringBuilder sb = new StringBuilder(1024);
for(int i=0; i<keys.length; i++) {
if(i!=0){
sb.append("&");
}
sb.append(keys[i]).append("=");
String value = param.get(keys[i]);
String valueString = "";
if (null != value) {
valueString = value;
}
if (encode) {
sb.append(urlEncode(valueString));
} else {
sb.append(valueString);
}
}
sb.append(secret);
return DigestUtils.sha256Hex(sb.toString());
}
private static String urlEncode(String str) {
try {
return URLEncoder.encode(str, UTF_8);
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("unsupported encoding:"+UTF_8, e);
}
}
三、基于token
服務(wù)端動(dòng)態(tài)生成token,客戶端調(diào)用的時(shí)候需要回傳token,參考 微信公共平臺(tái) access_token
3.1 JWT
JWT
參考資料
螞蟻金服開發(fā)平臺(tái) 簽名與驗(yàn)簽
微信公共平臺(tái) access_token
通過(guò)Spring Session實(shí)現(xiàn)新一代的Session管理