From f16c58f460a6e78399912e52f8de0b5bb3ac9dbd Mon Sep 17 00:00:00 2001 From: haozq <1611483981@qq.com> Date: Fri, 22 Mar 2024 15:16:34 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8A=A0=E8=A7=A3?= =?UTF-8?q?=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/TokenController.java | 6 +- .../common/core/utils/CommonConstant.java | 52 ++++ .../common/core/utils/aes/AesCbcUtils.java | 43 +++- .../common/core/utils/aes/MonoUtils.java | 38 +++ .../gateway/filter/GatewayContext.java | 43 ++++ .../gateway/filter/RequestCoverFilter.java | 236 ++++++++++++++++++ ...saDecryptResponseGatewayFilterFactory.java | 144 +++++++++++ .../service/impl/TeamServiceImpl.java | 2 +- 8 files changed, 546 insertions(+), 18 deletions(-) create mode 100644 securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/CommonConstant.java create mode 100644 securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/MonoUtils.java create mode 100644 securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/GatewayContext.java create mode 100644 securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RequestCoverFilter.java create mode 100644 securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java diff --git a/securitycontrol-auth/src/main/java/com/securitycontrol/auth/controller/TokenController.java b/securitycontrol-auth/src/main/java/com/securitycontrol/auth/controller/TokenController.java index 546e5ea..8e1ac8e 100644 --- a/securitycontrol-auth/src/main/java/com/securitycontrol/auth/controller/TokenController.java +++ b/securitycontrol-auth/src/main/java/com/securitycontrol/auth/controller/TokenController.java @@ -17,10 +17,7 @@ import io.jsonwebtoken.Claims; import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; @@ -56,7 +53,6 @@ public class TokenController { } - /** * 本地推出登录 * @param request diff --git a/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/CommonConstant.java b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/CommonConstant.java new file mode 100644 index 0000000..ec0d781 --- /dev/null +++ b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/CommonConstant.java @@ -0,0 +1,52 @@ +package com.securitycontrol.common.core.utils; + +import com.alibaba.fastjson2.JSONObject; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * @Author: meng + * @Description: 常用变量 + * @Date: 2023/3/30 10:29 + * @Version: 1.0 + */ +@Component +public class CommonConstant { + + //JWT密钥 + public static final String JWT_TOKEN = "jwt-token"; + + //请求头中的token + public static final String X_TOKEN = "X-TOKEN"; + + //请求头中的sign + public static final String X_SIGN = "X-SIGN"; + + public static final String X_APPID = "X-APPID"; + + public static final String CODE = "code"; + + public static final String MESSAGE = "message"; + + public static final String UTF8 = "UTF-8"; + + public static final String RSA_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFJIl4il6nDBlF/3byWB/KXRqfEXkviz7ZvO7TU7JBfh7sFqfgLtJFDSA33+qTHOtYTCjCrwl6oWWX7Aff39HiFW1IBnhKjYdSK5/8ruQY+Y2xbpBMgslA0m2euOv3XPJUXWh0JGBqPllgzvtbtUA1iBELAHVYBACuQPYP2VcPeQIDAQAB"; + public static final String RSA_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMUkiXiKXqcMGUX/dvJYH8pdGp8ReS+LPtm87tNTskF+HuwWp+Au0kUNIDff6pMc61hMKMKvCXqhZZfsB9/f0eIVbUgGeEqNh1Irn/yu5Bj5jbFukEyCyUDSbZ646/dc8lRdaHQkYGo+WWDO+1u1QDWIEQsAdVgEAK5A9g/ZVw95AgMBAAECgYABvRrBR2ciTgcDCQfBh2lwXXXYpUzOUIoTXYk1r+1IipY3OtPsND2CgmUgWQc2mPCybKmHXgfVXwsIVfqTzOOK+PEMVGYNflUdXgV3hNffRzl/nfPdpqhb2ALu8ftPwiGq5QN2PqaRgY9kM67Ye/cCjFzm/kLIqsNuXLKiQc1ioQJBAO7g4ZBcG/D0IxtiR4RdXYtr4wQc+cmscSKj5RPNBwn0bh9psOSg2loS/wWUmCnYSncsLGgMzPl+yPkTLwGryH0CQQDTRduiOzu6bFdOw6tI6eOxHB5h0kfcim4VT/Huh5RyP+GC7kLBmknbBO/tQXxSDVaG81Pkr+INHxJmctfKik+tAkEAtBIrl0IIAhRXnp3wYXRsPtxeLkyVc5SdWEqKNen5Y2Sx2tY2dbJXx0zIl3FTXz/fqoRPGUSFA5Kydygh6DWRlQJBAMmOfOHB9tJ8Z7LJ85AFKucdt1KFpW8eVbVZZqq0iAeTMBaULfW7tzgO9sJ3Vh6FgQYP//pNXbA883XvnDUrTKUCQQDgLO7mThmy7iqqo0be4a2ycy9fvORFYzSq1t6mTd+gr73CMCy2bTmyv/Qp4QsuPIKea0iE+HA/la5zlM8eAxOq"; + //公共返回方法 + public static Mono buildResponse(ServerWebExchange exchange, int code, String message) { + ServerHttpResponse response = exchange.getResponse(); + response.setStatusCode(HttpStatus.OK); + response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE); + JSONObject jsonObject = new JSONObject(); + jsonObject.put(CODE, code); + jsonObject.put(MESSAGE, message); + DataBuffer bodyDataBuffer = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes()); + return response.writeWith(Mono.just(bodyDataBuffer)); + } +} \ No newline at end of file diff --git a/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java index d69b45b..93644dc 100644 --- a/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java +++ b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java @@ -38,7 +38,7 @@ public class AesCbcUtils { /** * AES要求密钥长度为128位或192位或256位,java默认限制AES密钥长度最多128位 */ - public static String sKey = "zhst@bonus@zhst@bonus@1234567890"; + public static String sKey = "zhgd@bonus@zhgd@bonus@1234567890"; /** * 编码格式导出 @@ -58,26 +58,44 @@ public class AesCbcUtils { * @throws Exception * @return 加密后的密文 */ - public static String encrypt(String source, String key) throws Exception { - byte[] sourceBytes = source.getBytes(ENCODING); - byte[] keyBytes = key.getBytes(ENCODING); - Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC"); - IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(ENCODING)); - cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM), iv); - byte[] decrypted = cipher.doFinal(sourceBytes); - return Base64.encodeBase64String(decrypted); + public static String encrypt(String source ) { + try{ + String key=sKey; + byte[] sourceBytes = source.getBytes(ENCODING); + byte[] keyBytes = key.getBytes(ENCODING); + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC"); + IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(ENCODING)); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM), iv); + byte[] decrypted = cipher.doFinal(sourceBytes); + return Base64.encodeBase64String(decrypted); + }catch (Exception e){ + log.error(e.toString(),e); + } + return null; + } + + public static void main(String[] args) { + String json="username=guest&password=admin@123"; + + // String json="{\"username\":\"guest\",\"password\":\"admin@123\"}"; + String data=encrypt(json); + System.err.println(data); } /** * AES解密 *(CBC模式) - * @param encryptStr 加密后的密文 + * @param data 加密后的密文 * @param * @throws Exception * @return 源字符串 */ - public static String decrypt(String encryptStr) { + public static String decrypt(String data) { try{ + String encryptStr=""; + if(StringHelper.isNotEmpty(data)){ + encryptStr=data.replace(" ","+"); + } String key=sKey; byte[] sourceBytes = Base64.decodeBase64(encryptStr); byte[] keyBytes = key.getBytes(ENCODING); @@ -87,9 +105,10 @@ public class AesCbcUtils { byte[] decoded = cipher.doFinal(sourceBytes); return new String(decoded, ENCODING); }catch (Exception e){ + log.info("------------------->请求加密参数不正确"); log.error(e.toString(),e); - return null; } + return null; } } diff --git a/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/MonoUtils.java b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/MonoUtils.java new file mode 100644 index 0000000..26929ac --- /dev/null +++ b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/MonoUtils.java @@ -0,0 +1,38 @@ +package com.securitycontrol.common.core.utils.aes; + +import com.alibaba.fastjson2.JSONObject; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.nio.charset.StandardCharsets; + +/** + * @author 黑子 + */ +public final class MonoUtils { + + private MonoUtils() { + + } + public static Mono invalidUrl(ServerWebExchange exchange){ + JSONObject json = new JSONObject(); + json.put("code", 400); + json.put("msg", "无效的请求"); + return buildReturnMono(json, exchange); + } + + + public static Mono buildReturnMono(JSONObject json, ServerWebExchange exchange) { + ServerHttpResponse response = exchange.getResponse(); + byte[] bits = json.toJSONString().getBytes(StandardCharsets.UTF_8); + DataBuffer buffer = response.bufferFactory().wrap(bits); + response.setStatusCode(HttpStatus.UNAUTHORIZED); + //指定编码,否则在浏览器中会中文乱码 + response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8"); + return response.writeWith(Mono.just(buffer)); + } + +} diff --git a/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/GatewayContext.java b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/GatewayContext.java new file mode 100644 index 0000000..5ba76b3 --- /dev/null +++ b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/GatewayContext.java @@ -0,0 +1,43 @@ +package com.securitycontrol.gateway.filter; + +import lombok.Data; +import org.springframework.http.HttpHeaders; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +/** + * @Author: meng + * @Description: 网关上下文 + * @Version: 1.0 + */ +@Data +public class GatewayContext { + + public static final String CACHE_GATEWAY_CONTEXT = "cacheGatewayContext"; + + /** + * cache headers + */ + private HttpHeaders headers; + + /** + * cache json body + */ + private String cacheBody; + + /** + * cache formdata + */ + private MultiValueMap formData = new LinkedMultiValueMap<>(); + + /** + * ipAddress + */ + private String ipAddress; + + /** + * path + */ + private String path; + +} \ No newline at end of file diff --git a/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RequestCoverFilter.java b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RequestCoverFilter.java new file mode 100644 index 0000000..5512f6a --- /dev/null +++ b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RequestCoverFilter.java @@ -0,0 +1,236 @@ +package com.securitycontrol.gateway.filter; + +import io.netty.buffer.ByteBufAllocator; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +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.codec.HttpMessageReader; +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.reactive.function.server.HandlerStrategies; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; + +/** + * @Author: https://blog.csdn.net/zx156955/article/details/115004910 + * @Description: 请求内容存储 处理请求内容 内容放在gatewayContext中 + * @Date: 2023/3/30 10:11 + * @Version: 1.0 + */ +@Component +@Slf4j +public class RequestCoverFilter implements GlobalFilter, Ordered { + + /** + * default HttpMessageReader + */ + private static final List> messageReaders = HandlerStrategies.withDefaults().messageReaders(); + + /** + * ReadFormData + * + * @param exchange + * @param chain + * @return + */ + private Mono readFormData(ServerWebExchange exchange, GatewayFilterChain chain, + GatewayContext gatewayContext) { + final ServerHttpRequest request = exchange.getRequest(); + HttpHeaders headers = request.getHeaders(); + + return exchange.getFormData().doOnNext(multiValueMap -> { + gatewayContext.setFormData(multiValueMap); + log.debug("[GatewayContext]Read FormData:{}", multiValueMap); + }).then(Mono.defer(() -> { + Charset charset = headers.getContentType().getCharset(); + charset = charset == null ? StandardCharsets.UTF_8 : charset; + String charsetName = charset.name(); + MultiValueMap formData = gatewayContext.getFormData(); + /** + * formData is empty just return + */ + if (null == formData || formData.isEmpty()) { + return chain.filter(exchange); + } + StringBuilder formDataBodyBuilder = new StringBuilder(); + String entryKey; + List entryValue; + try { + /** + * repackage form data + */ + for (Map.Entry> entry : formData.entrySet()) { + entryKey = entry.getKey(); + entryValue = entry.getValue(); + if (entryValue.size() > 1) { + for (String value : entryValue) { + formDataBodyBuilder.append(entryKey).append("=") + .append(URLEncoder.encode(value, charsetName)).append("&"); + } + } else { + formDataBodyBuilder.append(entryKey).append("=") + .append(URLEncoder.encode(entryValue.get(0), charsetName)).append("&"); + } + } + } catch (UnsupportedEncodingException e) { + // ignore URLEncode Exception + } + /** + * substring with the last char '&' + */ + String formDataBodyString = ""; + if (formDataBodyBuilder.length() > 0) { + formDataBodyString = formDataBodyBuilder.substring(0, formDataBodyBuilder.length() - 1); + } + /** + * get data bytes + */ + byte[] bodyBytes = formDataBodyString.getBytes(charset); + int contentLength = bodyBytes.length; + ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(request) { + /** + * change content-length + * + * @return + */ + @Override + public HttpHeaders getHeaders() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.putAll(super.getHeaders()); + if (contentLength > 0) { + httpHeaders.setContentLength(contentLength); + } else { + httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); + } + return httpHeaders; + } + + /** + * read bytes to Flux + * + * @return + */ + @Override + public Flux getBody() { + return DataBufferUtils.read(new ByteArrayResource(bodyBytes), + new NettyDataBufferFactory(ByteBufAllocator.DEFAULT), contentLength); + } + }; + ServerWebExchange mutateExchange = exchange.mutate().request(decorator).build(); + log.info("[GatewayContext]Rewrite Form Data :{}", formDataBodyString); + + return chain.filter(mutateExchange); + })); + } + + /** + * ReadJsonBody + * + * @param exchange + * @param chain + * @return + */ + private Mono readBody(ServerWebExchange exchange, GatewayFilterChain chain, GatewayContext gatewayContext) { + /** + * join the body + */ + return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> { + /* + * read the body Flux, and release the buffer + * see PR https://github.com/spring-cloud/spring-cloud-gateway/pull/1095 + */ + byte[] bytes = new byte[dataBuffer.readableByteCount()]; + dataBuffer.read(bytes); + DataBufferUtils.release(dataBuffer); + Flux cachedFlux = Flux.defer(() -> { + DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes); + DataBufferUtils.retain(buffer); + return Mono.just(buffer); + }); + /** + * repackage ServerHttpRequest + */ + ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) { + @Override + public Flux getBody() { + return cachedFlux; + } + }; + /** + * mutate exchage with new ServerHttpRequest + */ + ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build(); + /** + * read body string with default messageReaders + */ + return ServerRequest.create(mutatedExchange, messageReaders).bodyToMono(String.class) + .doOnNext(objectValue -> { + gatewayContext.setCacheBody(objectValue); + log.debug("[GatewayContext]Read JsonBody:{}", objectValue); + }).then(chain.filter(mutatedExchange)); + }); + } + + @Override + public int getOrder() { + return HIGHEST_PRECEDENCE; + } + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + /** + * save request path and serviceId into gateway context + */ + ServerHttpRequest request = exchange.getRequest(); + ServerHttpResponse response = exchange.getResponse(); + + GatewayContext gatewayContext = new GatewayContext(); + String path = request.getPath().pathWithinApplication().value(); + gatewayContext.setPath(path); + gatewayContext.getFormData().addAll(request.getQueryParams()); + gatewayContext.setIpAddress(String.valueOf(request.getRemoteAddress())); + HttpHeaders headers = request.getHeaders(); + gatewayContext.setHeaders(headers); + log.debug("HttpMethod:{},Url:{}", request.getMethod(), request.getURI().getRawPath()); + + /// 注意,因为webflux的响应式编程 不能再采取原先的编码方式 即应该先将gatewayContext放入exchange中,否则其他地方可能取不到 + /** + * save gateway context into exchange + */ + exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext); + + // 处理参数 + MediaType contentType = headers.getContentType(); + long contentLength = headers.getContentLength(); + if (contentLength > 0) { + if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) { + return readBody(exchange, chain, gatewayContext); + } + if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) { + return readFormData(exchange, chain, gatewayContext); + } + } + + log.debug("[GatewayContext]ContentType:{},Gateway context is set with {}", contentType, gatewayContext); + return chain.filter(exchange); + } +} \ No newline at end of file diff --git a/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java new file mode 100644 index 0000000..06770ed --- /dev/null +++ b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java @@ -0,0 +1,144 @@ +package com.securitycontrol.gateway.filter; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.CryptoException; +import com.securitycontrol.common.core.utils.CommonConstant; +import com.securitycontrol.common.core.utils.StringUtils; +import com.securitycontrol.common.core.utils.aes.AesCbcUtils; +import com.securitycontrol.common.core.utils.aes.MonoUtils; +import com.securitycontrol.common.core.utils.aes.StringHelper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpRequestDecorator; +import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Flux; + +import java.lang.reflect.Field; +import java.net.URI; +import java.security.interfaces.RSAPrivateKey; + +/** + * @Author: meng + * @Description: RSA实现对请求参数解密 + * @Date: 2023/4/6 15:20 + * @Version: 1.0 + */ +@Slf4j +@Component +class RsaDecryptResponseGatewayFilterFactory extends AbstractGatewayFilterFactory { + + @Override + public GatewayFilter apply(Object config) { + return (exchange, chain) -> { + ServerHttpRequest serverHttpRequest = exchange.getRequest(); + HttpHeaders header = serverHttpRequest.getHeaders(); + String decrypt = serverHttpRequest.getHeaders().getFirst("decrypt"); + //get请求 默认 + if(HttpMethod.GET.matches(serverHttpRequest.getMethodValue())){//如果是get + if(exchange.getRequest().getQueryParams().isEmpty()){//如果参数是空的 + return chain.filter(exchange); + }else{ + try{ + updateRequestParam(exchange); + }catch (Exception e){ + log.error(e.toString(),e); + return CommonConstant.buildResponse(exchange, HttpStatus.BAD_REQUEST.value(), "请求参数异常"); + } + } + } + if (!HttpMethod.POST.matches(serverHttpRequest.getMethodValue())) {//非 post请求 + return chain.filter(exchange); + } + byte[] decrypBytes; + GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.CACHE_GATEWAY_CONTEXT); + if(StrUtil.isBlank(gatewayContext.getCacheBody())){ + if(!exchange.getRequest().getQueryParams().isEmpty()){ + try{ + updateRequestParam(exchange); + }catch (Exception e){ + log.error(e.toString(),e); + return CommonConstant.buildResponse(exchange, HttpStatus.BAD_REQUEST.value(), "请求参数异常"); + } + } + //未强制加密 + return chain.filter(exchange); + + // return CommonConstant.buildResponse(exchange, HttpStatus.BAD_REQUEST.value(), "请求参数不能为空"); + + } + try { + // 获取request body + String requestBody = gatewayContext.getCacheBody(); + String decryptMsg= AesCbcUtils.decrypt(requestBody); + gatewayContext.setCacheBody(decryptMsg); + decrypBytes = decryptMsg.getBytes(); + } catch (Exception e) { + log.error("数据 解密失败:{}", e); + return CommonConstant.buildResponse(exchange, HttpStatus.BAD_REQUEST.value(), "数据解密失败"); + } + // 根据解密后的参数重新构建请求 + DataBufferFactory dataBufferFactory = exchange.getResponse().bufferFactory(); + Flux bodyFlux = Flux.just(dataBufferFactory.wrap(decrypBytes)); + ServerHttpRequest newRequest = serverHttpRequest.mutate().uri(serverHttpRequest.getURI()).build(); + newRequest = new ServerHttpRequestDecorator(newRequest) { + @Override + public Flux getBody() { + return bodyFlux; + } + }; + // 构建新的请求头 + HttpHeaders headers = new HttpHeaders(); + headers.putAll(exchange.getRequest().getHeaders()); + // 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度 + int length = decrypBytes.length; + headers.remove(HttpHeaders.CONTENT_LENGTH); + headers.setContentLength(length); + newRequest = new ServerHttpRequestDecorator(newRequest) { + @Override + public HttpHeaders getHeaders() { + return headers; + } + }; + // 把解密后的数据重置到exchange自定义属性中,在之后的日志GlobalLogFilter从此处获取请求参数打印日志 + exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext); + return chain.filter(exchange.mutate().request(newRequest).build()); + }; + } + + + /** + * 修改前端传的参数 + */ + private void updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException { + ServerHttpRequest request = exchange.getRequest(); + URI uri = request.getURI(); + //请求参数 + String query = uri.getQuery(); + //判断是否有加密的参数 这里的约定是 param + if (StringUtils.isNotBlank(query) && query.contains("params")) { + String[] split = query.split("="); + String paramValue = split[1]; + //解密请求参数 + String param =AesCbcUtils.decrypt(paramValue); + //使用反射强行拿出 URI 的 query + Field targetQuery = uri.getClass().getDeclaredField("query"); + //授权 + targetQuery.setAccessible(true); + //重新设置参数 + targetQuery.set(uri, param); + } + } + + + +} \ No newline at end of file diff --git a/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/TeamServiceImpl.java b/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/TeamServiceImpl.java index b89e072..d619d07 100644 --- a/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/TeamServiceImpl.java +++ b/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/TeamServiceImpl.java @@ -55,7 +55,7 @@ public class TeamServiceImpl implements TeamService { } else { vo.setType(2); } - vo.setIdNumber(AesCbcUtils.encrypt(vo.getIdNumber(),AesCbcUtils.sKey)); + vo.setIdNumber(AesCbcUtils.encrypt(vo.getIdNumber())); mapper.addOrUpdateTeam(vo); } catch (Exception e) { log.error("新增/修改班组", e); From d90cf639dfa5035d0e5132bff4273273b30c09b7 Mon Sep 17 00:00:00 2001 From: haozq <1611483981@qq.com> Date: Fri, 22 Mar 2024 15:51:26 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8A=A0=E8=A7=A3?= =?UTF-8?q?=E5=AF=86=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- securitycontrol-auth/src/main/resources/bootstrap.yml | 4 ++++ .../common/core/utils/aes/AesCbcUtils.java | 4 ++-- .../filter/RsaDecryptResponseGatewayFilterFactory.java | 10 ++++++++-- .../src/main/resources/bootstrap.yml | 6 ++++-- .../background/service/impl/HumanServiceImpl.java | 4 ++-- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/securitycontrol-auth/src/main/resources/bootstrap.yml b/securitycontrol-auth/src/main/resources/bootstrap.yml index 2de2c49..541084a 100644 --- a/securitycontrol-auth/src/main/resources/bootstrap.yml +++ b/securitycontrol-auth/src/main/resources/bootstrap.yml @@ -19,10 +19,14 @@ spring: server-addr: 127.0.0.1:8848 # server-addr: 27.196.164.56:8848 namespace: jjzhgd + username: nacos + password: Jjsp@nacos2023 config: # server-addr: 27.196.164.56:8848 server-addr: 127.0.0.1:8848 namespace: jjzhgd + username: nacos + password: Jjsp@nacos2023 # 配置文件格式 file-extension: yml # 共享配置 diff --git a/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java index 93644dc..dc77acb 100644 --- a/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java +++ b/securitycontrol-commons/securitycontrol-commons-core/src/main/java/com/securitycontrol/common/core/utils/aes/AesCbcUtils.java @@ -75,9 +75,9 @@ public class AesCbcUtils { } public static void main(String[] args) { - String json="username=guest&password=admin@123"; + // String json="username=guest&password=admin@123"; - // String json="{\"username\":\"guest\",\"password\":\"admin@123\"}"; + String json="{\"username\":\"guest\",\"password\":\"admin@123\"}"; String data=encrypt(json); System.err.println(data); } diff --git a/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java index 06770ed..de9f518 100644 --- a/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java +++ b/securitycontrol-gateway/src/main/java/com/securitycontrol/gateway/filter/RsaDecryptResponseGatewayFilterFactory.java @@ -8,6 +8,7 @@ import com.securitycontrol.common.core.utils.aes.AesCbcUtils; import com.securitycontrol.common.core.utils.aes.MonoUtils; import com.securitycontrol.common.core.utils.aes.StringHelper; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.core.io.buffer.DataBuffer; @@ -37,12 +38,17 @@ import java.security.interfaces.RSAPrivateKey; @Component class RsaDecryptResponseGatewayFilterFactory extends AbstractGatewayFilterFactory { + @Value("${system.jm}") + public boolean AQ_JM; + + @Override public GatewayFilter apply(Object config) { return (exchange, chain) -> { ServerHttpRequest serverHttpRequest = exchange.getRequest(); - HttpHeaders header = serverHttpRequest.getHeaders(); - String decrypt = serverHttpRequest.getHeaders().getFirst("decrypt"); + if(!AQ_JM){ + return chain.filter(exchange); + } //get请求 默认 if(HttpMethod.GET.matches(serverHttpRequest.getMethodValue())){//如果是get if(exchange.getRequest().getQueryParams().isEmpty()){//如果参数是空的 diff --git a/securitycontrol-gateway/src/main/resources/bootstrap.yml b/securitycontrol-gateway/src/main/resources/bootstrap.yml index 98cb880..2f6e830 100644 --- a/securitycontrol-gateway/src/main/resources/bootstrap.yml +++ b/securitycontrol-gateway/src/main/resources/bootstrap.yml @@ -17,7 +17,7 @@ spring: nacos: discovery: username: nacos - password: nacos + password: Jjsp@nacos2023 namespace: jjzhgd # 服务注册地址 server-addr: 127.0.0.1:8848 @@ -32,7 +32,7 @@ spring: shared-configs: - vsc-dev.yml username: nacos - password: nacos + password: Jjsp@nacos2023 namespace: jjzhgd # server-addr: 10.138.132.188:18848 management: @@ -48,4 +48,6 @@ management: endpoints: env: enable: false +system: + jm: false diff --git a/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/HumanServiceImpl.java b/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/HumanServiceImpl.java index 1c1e9fb..5a624f9 100644 --- a/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/HumanServiceImpl.java +++ b/securitycontrol-model/securitycontrol-background/src/main/java/com/securitycontrol/background/service/impl/HumanServiceImpl.java @@ -39,7 +39,7 @@ public class HumanServiceImpl implements HumanService { @Resource(name = "HumanManageMapper") private HumanManageMapper mapper; - @Autowired + @Resource private RemoteFileService remoteFileService; @Resource(name = "ValidatorsUtils") @@ -111,7 +111,7 @@ public class HumanServiceImpl implements HumanService { } } } - vo.setIdNumber(AesCbcUtils.encrypt(vo.getIdNumber(),AesCbcUtils.sKey)); + vo.setIdNumber(AesCbcUtils.encrypt(vo.getIdNumber())); // 保存人员数据 mapper.addOrUpdatePersonnel(vo); } catch (Exception e) {