API接口的安全性主要是为了保证数据不会被篡改和重复调用,实现方案主要围绕Token、时间戳和Sign三个机制展开设计。
1. Token授权机制
用户使用用户名密码登录后服务器给客户端返回一个Token(必须要保证唯一,可以结合UUID和本地设备标示),并将Token-UserId以键值对的形式存放在缓存服务器中(我们是使用Redis),并要设置失效时间。服务端接收到请求后进行Token验证,如果Token不存在,说明请求无效。Token是客户端访问服务端的凭证。
# uuid 是手机设备的唯一标示
String token = UUID.randomUUID().toString() + "_" + uuid;
// timeStamp是客户端从Header传过来的值 Long timeStamp = RequestHeaderContext.getInstance().getTimeStamp(); boolean checkTime = checkTime(timeStamp, 30 * 1000); if (!checkTime) { return responseErrorAPISecurity(response); } // checkTime方法 public static boolean checkTime(Long time, Integer variable){ Long currentTimeMillis = System.currentTimeMillis(); Long addTime = currentTimeMillis + variable; Long subTime = currentTimeMillis - variable; if (addTime > time && time > subTime){ return true; } return false; }
// 请求的API参数,如果是再body,则MD5;如果是param,则原字符串 StringBuffer urlSign = new StringBuffer(); if ("POST".equals(request.getMethod()) || "PUT".equals(request.getMethod())) { String bodyStr = RequestReaderUtil.ReadAsChars(request); String bodySign = ""; if (!StringUtils.isEmpty(bodyStr)){ bodySign = DigestUtils.md5DigestAsHex((bodyStr).getBytes()); } urlSign = new StringBuffer(bodySign); } else if ("GET".equals(request.getMethod()) || "DELETE".equals(request.getMethod())) { String params = request.getQueryString(); if (params == null){ params = ""; } urlSign = new StringBuffer(params); } // “请求的API参数”+“时间戳”+“盐”进行MD5算法加密 String sign = DigestUtils.md5DigestAsHex(urlSign.append(timeStamp).append(salt).toString().getBytes()); // signature是客户端从Header传过来的值 if (signature.equals(sign)) { return true; } else { return false; }
/** * 登录后由服务端生成并返回 */ private String token; /** * 安全校验字段(接口参数+时间戳+加盐:取MD5生成) */ private String signature; /** * 设备唯一标识 */ private String udid; /** * 时间戳,13位,比如:1532942172000 */ private Long timeStamp;
原文:https://www.cnblogs.com/cat520/p/13562223.html