接口授权常见处理方案之token
服务提供方和调用方同时用某个算法计算出一个token,比较时间来确定token是否有效。
1 import org.springframework.util.Assert; 2 3 import javax.crypto.Mac; 4 import javax.crypto.SecretKey; 5 import javax.crypto.spec.SecretKeySpec; 6 import java.util.Base64; 7 import java.util.Date; 8 9 /** 10 * @Author: pengbenlei 11 * @Date: 2020/8/27 11:24 12 * @Description: 接口授权码工具类 13 */ 14 public class RequestApiAuthUtil { 15 16 static final Base64.Encoder encoder = Base64.getEncoder(); 17 18 /** 19 * 请求授权码加密算法 20 * 21 * @param applicationCode 应用唯一码 22 * @param applicationKey 应用私钥 23 * @param timestamp 时间戳 24 */ 25 public static String ecode(String applicationCode, String applicationKey, Long timestamp) { 26 String authCode = ""; 27 try { 28 authCode = encoder.encodeToString(HmacSHA1Encrypt(applicationCode, applicationKey + timestamp.toString())); 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } 32 return authCode; 33 } 34 35 /** 36 * 请求授权码验证 37 */ 38 public static Boolean authCodeVerification(String authCode, String applicationCode, String applicationKey, Long startTime) { 39 Long nowTime = new Date().getTime() / 1000; 40 long timeDifference = nowTime - startTime; 41 // 时间点相差的秒数 42 // 7200秒内视为有效 43 System.out.println("nowTime:" + nowTime + " startTime:" + startTime + " timeDifference" + timeDifference); 44 Assert.isTrue(!(timeDifference > 7200 || timeDifference < 0), "Error passing in timestamp"); 45 //验证授权码 46 String correctCode = ecode(applicationCode, applicationKey, startTime); 47 Assert.isTrue(correctCode.equals(authCode), "Authorization code error, please check the algorithm or timestamp!"); 48 return true; 49 } 50 51 52 private static final String MAC_NAME = "HmacSHA1"; 53 private static final String ENCODING = "UTF-8"; 54 55 public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception { 56 byte[] data = encryptKey.getBytes(ENCODING); 57 // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称 58 SecretKey secretKey = new SecretKeySpec(data, MAC_NAME); 59 // 生成一个指定 Mac 算法 的 Mac 对象 60 Mac mac = Mac.getInstance(MAC_NAME); 61 // 用给定密钥初始化 Mac 对象 62 mac.init(secretKey); 63 64 byte[] text = encryptText.getBytes(ENCODING); 65 // 完成 Mac 操作 66 return mac.doFinal(text); 67 } 68 }密钥生成验证工具类
1 import com.leenleda.common.config.LenledaConfig; 2 import com.leenleda.common.utils.RedisUtil; 3 import com.leenleda.wechat.utils.RequestApiAuthUtil; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.stereotype.Component; 6 import org.springframework.util.Assert; 7 import org.springframework.web.servlet.HandlerInterceptor; 8 9 import javax.annotation.Resource; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 13 /** 14 * @Author: pengbenlei 15 * @Date: 2020/8/27 15:02 16 * @Description: 17 */ 18 @Component 19 public class ApiAuthInterceptor implements HandlerInterceptor { 20 21 22 final 23 RedisUtil redisUtil; 24 25 public ApiAuthInterceptor(RedisUtil redisUtil) { 26 this.redisUtil = redisUtil; 27 } 28 29 30 @Override 31 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 32 // 验证token 33 String token = request.getHeader("token"); 34 Assert.notNull(token, "token can not be empty!"); 35 // 验证时间戳 36 Long timestamp = Long.valueOf(request.getHeader("timestamp")); 37 Assert.notNull(timestamp, "timestamp can not be empty!"); 38 // 验证公钥 39 String publicKey = request.getHeader("public_key"); 40 Assert.notNull(publicKey, "applicationCode can not be empty!"); 41 // 验证token有效性 42 RequestApiAuthUtil.authCodeVerification(token, publicKey, privateKey(), timestamp); 43 return true; 44 } 45 46 }拦截器验证请求