叶君翔 3 år sedan
förälder
incheckning
c131f53612

+ 0 - 3
lb-gateway/src/main/java/com/ydd/gateway/GatewayApplication.java

@@ -2,11 +2,8 @@ package com.ydd.gateway;
 
 import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
 import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-
-import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 
 /**

+ 36 - 47
lb-gateway/src/main/java/com/ydd/gateway/filter/AuthorizeGatewayFilterFactory.java

@@ -2,45 +2,27 @@ package com.ydd.gateway.filter;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.ydd.gateway.config.GatewayConfig;
 import com.ydd.gateway.service.FilterService;
 import com.ydd.gateway.service.GatewayContext;
 import com.ydd.gateway.service.RecorderServerHttpRequestDecorator;
 import com.ydd.gateway.util.StringUtils;
-import io.netty.buffer.ByteBufAllocator;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cloud.gateway.filter.GatewayFilter;
-import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
-import org.springframework.core.io.ByteArrayResource;
 import org.springframework.core.io.buffer.DataBuffer;
-import org.springframework.core.io.buffer.DataBufferUtils;
-import org.springframework.core.io.buffer.NettyDataBufferFactory;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
 import org.springframework.http.server.reactive.ServerHttpResponse;
 import org.springframework.stereotype.Component;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
 import java.nio.CharBuffer;
-import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
+import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -48,18 +30,19 @@ import java.util.concurrent.atomic.AtomicReference;
  *
  */
 @Component
+@Slf4j
 public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {
 
-    private static final Log logger = LogFactory.getLog(AuthorizeGatewayFilterFactory.class);
-
-//	private static final String AUTHORIZE_TOKEN = "clientId";
+    private static final String SIGN = "sign";
+    private static final String TIME_STAMP_KEY = "timeStamp";
+    private static final String APP_ID = "appId";
 
     @Autowired
     FilterService filterService;
 
     public AuthorizeGatewayFilterFactory() {
         super(Config.class);
-        logger.info("Loaded GatewayFilterFactory [Authorize]");
+        log.info("Loaded GatewayFilterFactory [Authorize]");
     }
 
     @Override
@@ -83,7 +66,7 @@ public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<
 
             // url白名单
             String url = request.getURI().getPath();
-            logger.info(GatewayConfig.NACOS_SERVER_ADDR);
+            log.info(GatewayConfig.NACOS_SERVER_ADDR);
             String path = request.getPath().pathWithinApplication().value();
             System.out.println(path.substring(path.indexOf("/", 1), path.lastIndexOf("/")));
             System.out.println(URL.contains(path.substring(path.indexOf("/", 1), path.lastIndexOf("/"))));
@@ -93,7 +76,9 @@ public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<
             HttpHeaders headers = request.getHeaders();
             String method = request.getMethodValue();
             MediaType contentType = headers.getContentType();
-            if ("POST".equals(method)&&MediaType.APPLICATION_JSON.equals(contentType)){
+            JSONObject requestParams = new JSONObject();
+            Map reqMap = new HashMap<>();
+            if ("POST".equals(method) && MediaType.APPLICATION_JSON.equals(contentType)) {
                 AtomicReference<String> requestBody = new AtomicReference<>("");
                 RecorderServerHttpRequestDecorator requestDecorator = new RecorderServerHttpRequestDecorator(request);
                 Flux<DataBuffer> body = requestDecorator.getBody();
@@ -102,41 +87,45 @@ public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<
                     requestBody.set(charBuffer.toString());
                 });
                 //获取body参数
-                JSONObject requestParams = JSONObject.parseObject(requestBody.get());
+                requestParams = JSONObject.parseObject(requestBody.get());
+                reqMap = JSON.parseObject(requestBody.get(), LinkedHashMap.class);
                 System.out.println("**********************"+requestParams);
             }
             if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)){
                 GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.CACHE_GATEWAY_CONTEXT);
                 System.out.println(gatewayContext.getFormData());
             }
-            if("GET".equals(method)){
-                MultiValueMap<String, String> map =  request.getQueryParams();
-                System.out.println("**********************"+JSONObject.toJSONString(map));
+            if("GET".equals(method)) {
+                reqMap = request.getQueryParams();
+                System.out.println("**********************"+JSONObject.toJSONString(reqMap));
             }
 
 
-//			String remoteIP = headers.getFirst("x-real-ip");
-//			if (!StringUtils.hasText(remoteIP)) {
-//				remoteIP = request.getRemoteAddress().getHostName();
-//			}
-
-            // 请求信息打印
-           // logInfo(request, headers);
-            TreeMap<String, String> params = new TreeMap<>();
-            String signStr = headers.getFirst("sign");
+			String remoteIP = headers.getFirst("x-real-ip");
+			if (!StringUtils.hasText(remoteIP)) {
+				remoteIP = request.getRemoteAddress().getHostName();
+                log.info("请求IP: {}" + remoteIP);
+			}
 
-            String sourceType = headers.getFirst("sourceType");
-            String time = headers.getFirst("time");// 日期 yyyymmddHHmiss
-            String nonce = headers.getFirst("nonce");// 随机数
-            if (StringUtils.hasText(sourceType)) {
-                params.put("sourceType", sourceType);
+            TreeMap<String, Object> params = new TreeMap<>(reqMap);
+            if (StringUtils.isNull(params.get(SIGN)) || StringUtils.isBlank(params.get(SIGN).toString())) {
+                String signStr = headers.getFirst(SIGN);
+                params.put(SIGN, signStr);
+            }
+            if (StringUtils.isNull(params.get(APP_ID)) || StringUtils.isBlank(params.get(APP_ID).toString())) {
+                String appId = headers.getFirst(APP_ID);
+                params.put(APP_ID, appId);
             }
 
-            params.put("time", time);
-            params.put("nonce", nonce);
+            if (StringUtils.isNull(params.get(TIME_STAMP_KEY))) {
+                String timeStamp = headers.getFirst(TIME_STAMP_KEY);
+                params.put(TIME_STAMP_KEY, timeStamp);
+            }
 
+            Set<String> exclude = new HashSet<>();
+            exclude.add(SIGN);
             // 签名校验
-            Mono<DataBuffer> mono = filterService.validateSign(params, signStr, response);
+            Mono<DataBuffer> mono = filterService.validateSign(params, exclude, response);
             if (mono != null) {
                 //return response.writeWith(mono);
             }

+ 60 - 80
lb-gateway/src/main/java/com/ydd/gateway/service/FilterService.java

@@ -1,14 +1,12 @@
 package com.ydd.gateway.service;
 
 import com.alibaba.fastjson.JSON;
-import com.ydd.gateway.filter.AuthorizeGatewayFilterFactory;
 import com.ydd.gateway.filter.ResponseObject;
-
-import com.ydd.gateway.util.Md5Util;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ydd.gateway.util.SignatureUtil;
+import com.ydd.gateway.util.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.server.reactive.ServerHttpResponse;
@@ -16,104 +14,86 @@ import org.springframework.stereotype.Component;
 import reactor.core.publisher.Mono;
 
 import java.nio.charset.StandardCharsets;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
+import java.util.Set;
 import java.util.TreeMap;
 
 @Component
+@Slf4j
+@RefreshScope
 public class FilterService {
 
-	private static final Log logger = LogFactory.getLog(AuthorizeGatewayFilterFactory.class);
+	private static final String SIGN = "sign";
+	private static final String TIME_STAMP_KEY = "timeStamp";
+	private static final String APP_ID = "appId";
+
+	// 超过10分钟,验签失败
+	private static final Long EXPIRE_TIME = 10 * 60 * 1000L;
 
-	private static final String AUTHORIZE_TOKEN = "clientId";
+	@Value("${openApp.info}")
+	private String openAppInfo;
 
-//	@Autowired
-//	RedisTemplate redisTemplate;
-	public Mono<DataBuffer> validateSign(TreeMap<String, String> params, String signStr, ServerHttpResponse response) {
-		if (StringUtils.isEmpty(signStr)) {
+	public Mono<DataBuffer> validateSign(TreeMap<String, Object> params, Set<String> excludeParams, ServerHttpResponse response) {
+		Object sign = params.get(SIGN);
+		if (StringUtils.isNull(sign)) {
 			ResponseObject data = new ResponseObject();
 			data.setResult("error");
 			data.setMsg("非法请求");
-			byte[] datas = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
-			DataBuffer buffer = response.bufferFactory().wrap(datas);
+			byte[] dataByte = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
+			DataBuffer buffer = response.bufferFactory().wrap(dataByte);
 			response.setStatusCode(HttpStatus.BAD_REQUEST);
 			return Mono.just(buffer);
 		}
 
-		// logger.info("签名参数" + params.toString());
-		// logger.info("签名值" + signStr);
-		// logger.info("签名后的值" + Md5Util.sign(params));
-
-		// 查看传过来的日期与当前日期比较相差几分钟
-		long min = getMin(params.get("time"));
-		if (min >= 3) {// 暂时定相差三分钟为无效请求
-			logger.info("相差三分钟为无效请求");
+		log.info("签名参数: {}" + params.toString());
+		Object timeStamp = params.get(TIME_STAMP_KEY);
+		long now = System.currentTimeMillis();
+//		if (timeStamp == null || Math.abs(now - Long.parseLong(timeStamp.toString())) > EXPIRE_TIME) {
+//			log.warn("签名过期!");
+//			ResponseObject data = new ResponseObject();
+//			data.setResult("error");
+//			data.setMsg("非法请求");
+//			byte[] datas = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
+//			DataBuffer buffer = response.bufferFactory().wrap(datas);
+//			response.setStatusCode(HttpStatus.BAD_REQUEST);
+//			return Mono.just(buffer);
+//		}
+
+		log.info("openAppInfo: {}", openAppInfo);
+
+		String appId = params.get(APP_ID).toString();
+		String appSecret = null;
+		if (StringUtils.isNotEmpty(openAppInfo)) {
+			String[] splits = openAppInfo.split(",");
+			for (String split : splits) {
+				String[] value = split.split("-");
+				String key = value[0].trim();
+				log.info("key: {}, appId: {}", key, appId);
+				if (key.equals(appId)) {
+					appSecret = value[1];
+				}
+			}
+		}
+		// 获取appSecret
+		if (appSecret == null) {
 			ResponseObject data = new ResponseObject();
 			data.setResult("error");
-			data.setMsg("非法请求");
-			byte[] datas = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
-			DataBuffer buffer = response.bufferFactory().wrap(datas);
-			response.setStatusCode(HttpStatus.BAD_REQUEST);
+			data.setMsg("应用信息获取失败");
+			byte[] dataByte = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
+			DataBuffer buffer = response.bufferFactory().wrap(dataByte);
+			response.setStatusCode(HttpStatus.UNAUTHORIZED);
 			return Mono.just(buffer);
 		}
-
-		boolean right = Md5Util.verifySign(params, signStr);
-		if (!right) {
+		boolean checkResult = SignatureUtil.checkSignature(params, excludeParams, appSecret);
+		if (!checkResult) {
 			ResponseObject data = new ResponseObject();
 			data.setResult("error");
 			data.setMsg("签名不合法");
-			byte[] datas = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
-			DataBuffer buffer = response.bufferFactory().wrap(datas);
+			byte[] dataByte = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
+			DataBuffer buffer = response.bufferFactory().wrap(dataByte);
 			response.setStatusCode(HttpStatus.UNAUTHORIZED);
-
 			return Mono.just(buffer);
 		}
 		return null;
 	}
 
-
-
-	/**
-	 * 比较与当前时间相差几分钟
-	 * 
-	 * @param time
-	 * @return
-	 * @throws Exception
-	 */
-	public long getMin(String time) {
-		long nd = 1000 * 24 * 60 * 60;
-
-		long nh = 1000 * 60 * 60;
-
-		long nm = 1000 * 60;
-
-		// long ns = 1000;
-
-		// 获得两个时间的毫秒时间差异
-		// String time = "20190321141020";
-		Calendar cal = Calendar.getInstance();
-		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
-		long diff = 0;
-		try {
-			diff = cal.getTimeInMillis() - sdf.parse(time).getTime();
-		}
-		catch (ParseException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-
-		// 计算差多少天
-		long day = diff / nd;
-
-		// 计算差多少小时
-		long hour = diff % nd / nh;
-
-		// 计算差多少分钟
-		long min = diff % nd % nh / nm;
-
-		// 计算差多少秒//输出结果
-		// long sec = diff % nd % nh % nm / ns;
-		return min;
-	}
 }

+ 52 - 0
lb-gateway/src/main/java/com/ydd/gateway/util/SignatureUtil.java

@@ -0,0 +1,52 @@
+package com.ydd.gateway.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * @author 叶君翔
+ * @date 2022/02/23 21:35
+ */
+@Slf4j
+public class SignatureUtil {
+
+    public static boolean checkSignature(TreeMap<String, Object> params, Set<String> exclude, String appSecret) {
+        Object oldSign = params.get("sign");
+        log.info("oleSign: {}", oldSign);
+        String str2Sign = buildRequestParam4Sign(params, exclude, appSecret);
+        log.info("签名前的字符串: {}", str2Sign);
+        String newSign = Md5Util.md5(str2Sign).toUpperCase();
+        log.info("newSign: {}", newSign);
+        return oldSign.equals(newSign);
+    }
+
+    private static String buildRequestParam4Sign(Map<String, Object> paramMap, Set<String> excludeParams, String appSecret) {
+        Set<String> keySet = paramMap.keySet();
+        StringBuilder param = new StringBuilder(20 * keySet.size());
+        String[] keys = keySet.toArray(new String[keySet.size()]);
+        Arrays.sort(keys);
+        try {
+            for (String key : keys) {
+                if (excludeParams != null && excludeParams.contains(key)) {
+                    continue;
+                }
+                Object value = paramMap.get(key);
+                // 排除值为null的情况
+                if (value != null) {
+                    param.append(URLEncoder.encode(key, "UTF-8")).append("=").append(value).append("&");
+                }
+            }
+            param.append("appSecret").append("=").append(URLEncoder.encode(appSecret, "UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return param.toString();
+    }
+
+}

+ 30 - 0
lb-gateway/src/main/resources/application-dev.yml

@@ -0,0 +1,30 @@
+# Tomcat
+server:
+  port: 8087
+# Spring
+spring:
+  cloud:
+    gateway:
+      #default-filters:
+      #- Authorize=true
+      discovery:
+        locator:
+          enabled: false
+      routes:
+        - id: api-beta
+          uri: lb://lb-app
+          # uri: http://www.baidu.com/
+          predicates:
+            #匹配所有请求路径以
+            - Path=/api/**
+#            - Header=citycode,0512
+          filters:
+            - Authorize=true
+        - id: api-release
+          uri: lb://lb-app
+          #  uri:  http://www.2500sz.com/
+          predicates:
+            #匹配所有请求路径以
+            - Path=/**
+          filters:
+            - Authorize=true

+ 1 - 1
lb-gateway/src/main/resources/bootstrap-dev.yml

@@ -13,5 +13,5 @@ spring:
       # 共享配置
         shared-configs[0]:
           data-id: lb_application-dev.yaml
-          refresh: false
+          refresh: true