public void addInterceptors(InterceptorRegistry registry) {
//接口簽名認證攔截器,該簽名認證比較簡單,實際項目中可以使用Json Web Token或其他更好的方式替代。
if (!"dev".equals(env)) { //開發環境忽略簽名認證
registry.addInterceptor(new HandlerInterceptorAdapter() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//驗證簽名
boolean pass = validateSign(request);
if (pass) {
return true;
} else {
logger.warn("簽名認證失敗,請求接口:{},請求IP:{},請求參數:{}",
request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
Result result = new Result();
result.setCode(ResultCode.UNAUTHORIZED).setMessage("簽名認證失敗");
responseResult(response, result);
return false;
}
}
});
}
}
/**
* 一個簡單的簽名認證,規則:
* 1. 將請求參數按ascii碼排序
* 2. 拼接爲a=value&b=value...這樣的字符串(不包含sign)
* 3. 混合密鑰(secret)進行md5獲得簽名,與請求的簽名進行比較
*/
private boolean validateSign(HttpServletRequest request) {
String requestSign = request.getParameter("sign");//獲得請求籤名,如sign=19e907700db7ad91318424a97c54ed57
if (StringUtils.isEmpty(requestSign)) {
return false;
}
List<String> keys = new ArrayList<String>(request.getParameterMap().keySet());
keys.remove("sign");//排除sign參數
Collections.sort(keys);//排序
StringBuilder sb = new StringBuilder();
for (String key : keys) {
sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串
}
String linkString = sb.toString();
linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最後一個'&'
String secret = "Potato";//密鑰,自己修改
String sign = DigestUtils.md5Hex(linkString + secret);//混合密鑰md5
return StringUtils.equals(sign, requestSign);//比較
}