Browse Source

第三方接口签名验证DEMO

wub 4 years ago
parent
commit
db38ae09e7

+ 2 - 1
src/main/java/com/uas/eis/UasEisApplication.java

@@ -16,7 +16,8 @@ import com.uas.eis.core.support.TokenPropertiesListener;
 public class UasEisApplication {
 	public static void main(String[] args) {
 		SpringApplication application = new SpringApplication(UasEisApplication.class);
-		application.addListeners(new TokenPropertiesListener("token.properties"));
+		//application.addListeners(new TokenPropertiesListener("token.properties"));
+		application.addListeners(new TokenPropertiesListener("api_sign_key_mapping.properties"));
 		application.run(args);
 	}
 	

+ 105 - 0
src/main/java/com/uas/eis/controller/ApiSignLoginInterceptor.java

@@ -0,0 +1,105 @@
+package com.uas.eis.controller;
+
+import com.uas.eis.core.support.TokenProperties;
+import com.uas.eis.entity.ErrorMsg;
+import com.uas.eis.exception.SystemException;
+import com.uas.eis.utils.MD5Util;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
+import java.util.*;
+
+@Service
+public class ApiSignLoginInterceptor extends HandlerInterceptorAdapter {
+
+    // 签名超时时长,默认时间为5分钟,ms
+    private static final int SIGN_EXPIRED_TIME = 5 * 60 * 1000;
+    private static final String ACCESS_KEY = "AccessKey";
+    private static final String ACCESS_SECRET = "AccessSecret";
+    private static final String TIMESTAMP_KEY = "Timestamp";
+    private static final String SIGN_KEY = "Signature";
+    private static final String RequestId = "RequestId";
+    private static Map<String,String> tokenConfig = TokenProperties.getAllProperty();
+
+
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        String timestamp = request.getParameter(TIMESTAMP_KEY);
+        String accessKey = request.getParameter(ACCESS_KEY);
+        String requestId = request.getParameter(RequestId);
+
+        String accessSecret = tokenConfig.get(accessKey);
+
+        if (!StringUtils.isNumeric(timestamp)) {
+            throw new SystemException(ErrorMsg.TIMESTAMP_ILLEGAL);
+        }
+
+        // 检查KEY是否合理
+        if (StringUtils.isEmpty(accessKey) || StringUtils.isEmpty(accessSecret)) {
+            throw new SystemException(ErrorMsg.ACCESSKEY_ILLEGAL);
+        }
+
+        Long ts = Long.valueOf(timestamp);
+        // 禁止超时签名
+        if (System.currentTimeMillis() - ts > SIGN_EXPIRED_TIME) {
+            throw new SystemException(ErrorMsg.TIMEOUT_ILLEGAL);
+        }
+
+        String regex = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
+        if (!requestId.matches(regex)) {
+            throw new SystemException(ErrorMsg.REQUESTID_ILLEGAL);
+        }
+
+        if (!verificationSign(request, accessKey, accessSecret)) {
+            throw new SystemException(ErrorMsg.SIGNATURE_ILLEGAL);
+        }
+        return true;
+    }
+
+    private boolean verificationSign(HttpServletRequest request, String accessKey, String accessSecret) throws UnsupportedEncodingException {
+        Enumeration<?> pNames = request.getParameterNames();
+        Map<String, Object> params = new HashMap<String, Object>();
+        while (pNames.hasMoreElements()) {
+            String pName = (String) pNames.nextElement();
+            if (SIGN_KEY.equals(pName)) continue;
+            Object pValue = request.getParameter(pName);
+            params.put(pName, pValue);
+        }
+        String originSign = request.getParameter(SIGN_KEY);
+        String sign = createSign(params, accessSecret);
+        System.out.println(sign);
+
+        return sign.equals(originSign);
+    }
+
+    private String createSign(Map<String, Object> params, String accessSecret) throws UnsupportedEncodingException {
+        Set<String> keysSet = params.keySet();
+        Object[] keys = keysSet.toArray();
+        Arrays.sort(keys);
+        StringBuilder temp = new StringBuilder();
+        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);
+            }
+            temp.append(valueString);
+        }
+        temp.append("&").append(ACCESS_SECRET).append("=").append(accessSecret);
+        System.out.println(temp);
+        System.out.println(MD5Util.getEncryption(temp.toString()));
+        return MD5Util.getEncryption(temp.toString()).toUpperCase();
+    }
+}

+ 14 - 9
src/main/java/com/uas/eis/core/WebAppConfig.java

@@ -1,10 +1,9 @@
 package com.uas.eis.core;
 
-import java.nio.charset.Charset;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.uas.eis.controller.ApiSignLoginInterceptor;
+import com.uas.eis.core.support.DataSourceInterceptor;
+import com.uas.eis.core.support.LoginInterceptor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.converter.HttpMessageConverter;
@@ -14,9 +13,9 @@ import org.springframework.web.servlet.config.annotation.ContentNegotiationConfi
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.uas.eis.core.support.DataSourceInterceptor;
-import com.uas.eis.core.support.LoginInterceptor;
+import java.nio.charset.Charset;
+import java.text.SimpleDateFormat;
+import java.util.List;
 
 @Configuration
 public class WebAppConfig extends WebMvcConfigurationSupport{
@@ -25,9 +24,15 @@ public class WebAppConfig extends WebMvcConfigurationSupport{
 	public LoginInterceptor loginInterceptor(){
 		return new LoginInterceptor();
 	}
+
+	@Bean
+	public ApiSignLoginInterceptor apiSignLoginInterceptor(){
+		return new ApiSignLoginInterceptor();
+	}
 	
 	public void addInterceptors(InterceptorRegistry registry){
-		registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/EIS/login");
+		registry.addInterceptor(apiSignLoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/EIS/login");
+		//registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/EIS/login");
 		registry.addInterceptor(new DataSourceInterceptor()).addPathPatterns("/*/**");
 	}
 	

+ 7 - 0
src/main/java/com/uas/eis/entity/ErrorMsg.java

@@ -5,6 +5,13 @@ package com.uas.eis.entity;
  * 异常处理返回信息
  */
 public enum ErrorMsg {
+
+    TIMESTAMP_ILLEGAL(1001,"Timestamp is illegal","请求时间戳不合法"),
+    ACCESSKEY_ILLEGAL(1002,"AccessKey is illegal","加密KEY不合法"),
+    TIMEOUT_ILLEGAL(1003,"Time is Out","请求超时"),
+    REQUESTID_ILLEGAL(1004,"RequestId is illegal","随机字符串不合法"),
+    SIGNATURE_ILLEGAL(1005,"Signature is illegal","签名错误"),
+
     NULL_TOKEN(10001,"token not found","缺失token,请把token做为参数传入"),
     INVALID_TOKEN(10002,"invalid token","无效的token,请重新申请token"),
     EXPIRED_TOKEN(10003,"expired token","token已过期,请重新申请token"),

+ 1 - 0
src/main/resources/api_sign_key_mapping.properties

@@ -0,0 +1 @@
+test=testsecret1