Преглед изворни кода

实现GET请求参数加密

Li Yuan пре 1 година
родитељ
комит
db024a6e5a

+ 32 - 0
ibps-basic-root/modules/basic-response/src/main/java/com/lc/ibps/cloud/util/AESUtil.java

@@ -0,0 +1,32 @@
+package com.lc.ibps.cloud.util;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+public class AESUtil {
+    private static final String KEY = "dmngJmmO+9GMw+tu";
+    private static final String IV = "sanXyqhk8+U7LPP4";
+    public static String decrypt(String encryptedText)
+            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
+            IllegalBlockSizeException, BadPaddingException {
+        byte[] encryptedData = Base64.getDecoder().decode(encryptedText);
+
+        SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), "AES");
+        IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8));
+
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 使用CBC模式和PKCS5Padding填充
+        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
+
+        byte[] decryptedBytes = cipher.doFinal(encryptedData);
+        return new String(decryptedBytes, StandardCharsets.UTF_8).trim(); // 去除末尾空格
+    }
+}

+ 6 - 5
ibps-basis-root/modules/basis-zuul/src/main/java/com/lc/ibps/cloud/config/FilterInitialConfigure.java

@@ -1,13 +1,9 @@
 package com.lc.ibps.cloud.config;
 
+import com.lc.ibps.cloud.gateway.filter.*;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
-import com.lc.ibps.cloud.gateway.filter.AccessTokenFilter;
-import com.lc.ibps.cloud.gateway.filter.GatewayFilter;
-import com.lc.ibps.cloud.gateway.filter.GatewayPostFilter;
-import com.lc.ibps.cloud.gateway.filter.IpFilter;
-
 @Configuration
 public class FilterInitialConfigure {
 	
@@ -50,5 +46,10 @@ public class FilterInitialConfigure {
 	public AccessTokenFilter accessTokenFilter(){
 		return new AccessTokenFilter();
 	}
+
+	@Bean
+	public SignFilter signFilter() {
+		return new SignFilter();
+	}
 	
 }

+ 168 - 0
ibps-basis-root/modules/basis-zuul/src/main/java/com/lc/ibps/cloud/gateway/filter/SignFilter.java

@@ -0,0 +1,168 @@
+package com.lc.ibps.cloud.gateway.filter;
+
+import com.lc.ibps.api.base.constants.StateEnum;
+import com.lc.ibps.cloud.entity.APIResult;
+import com.lc.ibps.cloud.util.AESUtil;
+import com.netflix.zuul.ZuulFilter;
+import com.netflix.zuul.context.RequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 处理请求参数filter
+ *
+ * @author :liuqi
+ * @date :2018-08-29 14:11.
+ */
+@Component
+public class SignFilter extends ZuulFilter {
+
+    private static Logger log = LoggerFactory.getLogger(SignFilter.class);
+
+    /**
+     * pre:路由之前
+     * routing:路由之时
+     * post: 路由之后
+     * error:发送错误调用
+     *
+     * @return
+     */
+    @Override
+    public String filterType() {
+        return "pre";
+    }
+
+    /**
+     * filterOrder:过滤的顺序
+     *
+     * @return
+     */
+    @Override
+    public int filterOrder() {
+        return 0;
+    }
+
+    /**
+     * shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤
+     *
+     * @return
+     */
+    @Override
+    public boolean shouldFilter() {
+        return true;
+    }
+
+    /**
+     * run:过滤器的具体逻辑。
+     * 要把请求参数进行验签(解密)之后传给后续的微服务,首先获取到request,但是在request中只有getParameter()而没有setParameter()方法
+     * 所以直接修改url参数不可行,另外在reqeust中虽然可以使用setAttribute(),但是可能由于作用域(request)的不同,一台服务器中才能getAttribute
+     * 在这里设置的attribute在后续的微服务中是获取不到的,因此必须考虑另外的方式:即获取请求的输入流,并重写,即重写json参数,
+     * ctx.setRequest(new HttpServletRequestWrapper(request) {}),这种方式可重新构造上下文中的request
+     *
+     * @return
+     */
+    @Override
+    public Object run() {
+
+        // 获取到request
+        RequestContext ctx = RequestContext.getCurrentContext();
+        HttpServletRequest request = ctx.getRequest();
+        // 获取请求参数name
+        String name = "";
+        try {
+
+            // 请求方法
+            String method = request.getMethod();
+//            log.info(String.format("%s >>> %s", method, request.getRequestURL().toString()));
+//            // 获取请求的输入流
+//            InputStream in = request.getInputStream();
+//            String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
+//            // 如果body为空初始化为空json
+//            if (StringUtils.isBlank(body)) {
+//                body = "{}";
+//            }
+//            log.info("body" + body);
+//            // 转化成json
+//            JSONObject json = JSONObject.fromObject(body);
+
+            // get方法和post、put方法处理方式不同
+            if ("GET".equals(method)) {
+
+                // 获取请求参数name
+                name = request.getParameter("_p");
+
+                if (name != null) {
+                    // 关键步骤,一定要get一下,下面才能取到值requestQueryParams
+                    request.getParameterMap();
+                    Map<String, List<String>> requestQueryParams = ctx.getRequestQueryParams();
+                    if (requestQueryParams == null) {
+                        requestQueryParams = new HashMap<>();
+                    }
+                    List<String> arrayList = new ArrayList<>();
+                    String aes_decodedStr = AESUtil.decrypt(name);
+                    arrayList.add(aes_decodedStr + "");
+                    requestQueryParams.put("decodename", arrayList);
+                    ctx.setRequestQueryParams(requestQueryParams);
+                }
+            }// post和put需重写HttpServletRequestWrapper
+            /*else if ("POST".equals(method) || "PUT".equals(method)) {
+
+                // 获取请求参数name
+                name = json.getString("_p");
+
+                if (name != null) {
+
+//                String aes_encodedStr = AESUtil.getInstance().encode(name, key);
+//                log.info("加密:" + aes_encodedStr);
+//                json.put("decodename", aes_decodedStr);
+                    String aes_decodedStr = AESUtil.decrypt(name);
+                    log.info("解密:" + aes_decodedStr);
+
+                    // 把解密之后的参数放到json里
+                    json.put("decodename", aes_decodedStr);
+                    String newBody = json.toString();
+                    log.info("newBody" + newBody);
+                    final byte[] reqBodyBytes = newBody.getBytes();
+
+                    // 重写上下文的HttpServletRequestWrapper
+                    ctx.setRequest(new HttpServletRequestWrapper(request) {
+                        @Override
+                        public ServletInputStream getInputStream() throws IOException {
+                            return new ServletInputStreamWrapper(reqBodyBytes);
+                        }
+
+                        @Override
+                        public int getContentLength() {
+                            return reqBodyBytes.length;
+                        }
+
+                        @Override
+                        public long getContentLengthLong() {
+                            return reqBodyBytes.length;
+                        }
+                    });
+                }
+            }*/
+
+        } catch (Exception e) {
+            ctx.setSendZuulResponse(false);
+            ctx.setResponseStatusCode(401);
+
+            APIResult<Void> result = new APIResult<Void>();
+            result.setState(StateEnum.ILLEGAL_REQUEST.getCode());
+            result.setCause("Illegal request parameter!");
+            ctx.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
+            ctx.setResponseBody(result.toString());
+            ctx.set("isSuccess", false);
+        }
+        return null;
+    }
+}