diff --git a/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java b/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java index 84aecfc..b1e2c25 100644 --- a/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java +++ b/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java @@ -1,181 +1,181 @@ -package com.bonus.gateway.filter; - -import com.bonus.common.core.exception.CaptchaException; -import com.bonus.common.core.utils.StringUtils; -import com.bonus.common.core.utils.encryption.AesCbcUtils; -import com.bonus.common.core.utils.encryption.Sm3Util; -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.GatewayFilterChain; -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.core.io.buffer.DataBufferUtils; -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.CollectionUtils; -import org.springframework.util.MultiValueMap; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.util.UriComponentsBuilder; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Slf4j -@Component -public class AecDecryptParamFilter extends AbstractGatewayFilterFactory { - - public boolean decryptEnabled = true; - - public static final String HEADER_NAME = "decrypt"; - public static final String HMAC_HEADER_NAME = "Params-Hash"; - - @Override - public GatewayFilter apply(Object config) { - return (exchange, chain) -> { - if (!decryptEnabled) { - log.info("解密功能已禁用,直接继续过滤链。"); - return chain.filter(exchange); - } - ServerHttpRequest request = exchange.getRequest(); - boolean hasContentHeader = request.getHeaders().containsKey("Content-Type"); - if (hasContentHeader) { - return handlePostPutRequest(exchange, chain); - } else { - return handleGetRequest(exchange, chain); - } - }; - } - - private Mono handleGetRequest(ServerWebExchange exchange, GatewayFilterChain chain) { - try { - ServerWebExchange updatedExchange = updateRequestParam(exchange); - if (updatedExchange != null) { - return chain.filter(updatedExchange); - } else { - return chain.filter(exchange); - } - } catch (Exception e) { - log.error("处理 GET 请求时发生错误: {}", e.getMessage(), e); - exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); - return exchange.getResponse().setComplete(); - } - } - - private Mono handlePostPutRequest(ServerWebExchange exchange, GatewayFilterChain chain) { - return DataBufferUtils.join(exchange.getRequest().getBody()) - .flatMap(dataBuffer -> { - byte[] body = new byte[dataBuffer.readableByteCount()]; - dataBuffer.read(body); - DataBufferUtils.release(dataBuffer); - - String requestBody = new String(body, StandardCharsets.UTF_8); - // 去掉多余的引号(如果有) - if (requestBody.startsWith("\"") && requestBody.endsWith("\"")) { - requestBody = requestBody.substring(1, requestBody.length() - 1); - } - - String decryptedBody; - try { - String providedHmac = exchange.getRequest().getHeaders().getFirst(HMAC_HEADER_NAME); - integrityVerification(providedHmac, requestBody); - decryptedBody = AesCbcUtils.decrypt(requestBody); - } catch (Exception e) { - log.error("解密请求体时发生错误: {}", e.getMessage(), e); - exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); - return exchange.getResponse().setComplete(); - } - - DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory(); - DataBuffer newBody = bufferFactory.wrap(decryptedBody.getBytes(StandardCharsets.UTF_8)); - ServerHttpRequest newRequest = createNewRequest(exchange, newBody); - - return chain.filter(exchange.mutate().request(newRequest).build()); - }); - } - - private ServerHttpRequest createNewRequest(ServerWebExchange exchange, DataBuffer newBody) { - return new ServerHttpRequestDecorator(exchange.getRequest()) { - @Override - public Flux getBody() { - return Flux.just(newBody); - } - - @Override - public HttpHeaders getHeaders() { - HttpHeaders headers = new HttpHeaders(); - headers.putAll(exchange.getRequest().getHeaders()); - headers.remove(HttpHeaders.CONTENT_LENGTH); - headers.setContentLength(newBody.readableByteCount()); - return headers; - } - }; - } - - private ServerWebExchange updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException { - ServerHttpRequest request = exchange.getRequest(); - URI uri = request.getURI(); - String query = uri.getQuery(); - if (StringUtils.isNotBlank(query)) { - String providedHmac = exchange.getRequest().getHeaders().getFirst(HMAC_HEADER_NAME); - integrityVerification(providedHmac, query); - String decryptedParam; - try { - decryptedParam = AesCbcUtils.decrypt(query); - } catch (Exception e) { - log.error("解密查询参数时发生错误: {}", e.getMessage(), e); - throw new CaptchaException("请求参数不正确"); - } - if (StringUtils.isEmpty(decryptedParam)) { - return null; - } - Map> queryParams = Arrays.stream(decryptedParam.split("&")) - .map(param -> param.split("=")) - .collect(Collectors.toMap( - param -> param[0], - param -> Collections.singletonList(param[1]) - )); - URI newUri = UriComponentsBuilder.fromUri(uri) - .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParams)) - .build(true) - .toUri(); - - ServerHttpRequest newRequest = request.mutate().uri(newUri).build(); - - return exchange.mutate().request(newRequest).build(); - } - return null; - } - - /** - * 数据完整性校验 - * - * @param providedHmac 请求头中的 HMAC 值 - * @param query 请求参数 - */ - private void integrityVerification(String providedHmac, String query) { - /* if (providedHmac == null) { - log.error("请求头中缺少 Params-Hash"); - throw new CaptchaException("请求参数不正确"); - } - String encrypt = Sm3Util.encrypt(query); - log.debug("加密后的参数: {}", encrypt); - log.debug("请求头中的 Params-Hash: {}", providedHmac); - if (!encrypt.equals(providedHmac)) { - log.error("参数校验失败"); - throw new CaptchaException("请求参数不正确"); - }*/ - } -} +//package com.bonus.gateway.filter; +// +//import com.bonus.common.core.exception.CaptchaException; +//import com.bonus.common.core.utils.StringUtils; +//import com.bonus.common.core.utils.encryption.AesCbcUtils; +//import com.bonus.common.core.utils.encryption.Sm3Util; +//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.GatewayFilterChain; +//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.core.io.buffer.DataBufferUtils; +//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.CollectionUtils; +//import org.springframework.util.MultiValueMap; +//import org.springframework.web.server.ServerWebExchange; +//import org.springframework.web.util.UriComponentsBuilder; +//import reactor.core.publisher.Flux; +//import reactor.core.publisher.Mono; +// +//import java.net.URI; +//import java.nio.charset.StandardCharsets; +//import java.util.Arrays; +//import java.util.Collections; +//import java.util.List; +//import java.util.Map; +//import java.util.stream.Collectors; +// +//@Slf4j +//@Component +//public class AecDecryptParamFilter extends AbstractGatewayFilterFactory { +// +// public boolean decryptEnabled = true; +// +// public static final String HEADER_NAME = "decrypt"; +// public static final String HMAC_HEADER_NAME = "Params-Hash"; +// +// @Override +// public GatewayFilter apply(Object config) { +// return (exchange, chain) -> { +// if (!decryptEnabled) { +// log.info("解密功能已禁用,直接继续过滤链。"); +// return chain.filter(exchange); +// } +// ServerHttpRequest request = exchange.getRequest(); +// boolean hasContentHeader = request.getHeaders().containsKey("Content-Type"); +// if (hasContentHeader) { +// return handlePostPutRequest(exchange, chain); +// } else { +// return handleGetRequest(exchange, chain); +// } +// }; +// } +// +// private Mono handleGetRequest(ServerWebExchange exchange, GatewayFilterChain chain) { +// try { +// ServerWebExchange updatedExchange = updateRequestParam(exchange); +// if (updatedExchange != null) { +// return chain.filter(updatedExchange); +// } else { +// return chain.filter(exchange); +// } +// } catch (Exception e) { +// log.error("处理 GET 请求时发生错误: {}", e.getMessage(), e); +// exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); +// return exchange.getResponse().setComplete(); +// } +// } +// +// private Mono handlePostPutRequest(ServerWebExchange exchange, GatewayFilterChain chain) { +// return DataBufferUtils.join(exchange.getRequest().getBody()) +// .flatMap(dataBuffer -> { +// byte[] body = new byte[dataBuffer.readableByteCount()]; +// dataBuffer.read(body); +// DataBufferUtils.release(dataBuffer); +// +// String requestBody = new String(body, StandardCharsets.UTF_8); +// // 去掉多余的引号(如果有) +// if (requestBody.startsWith("\"") && requestBody.endsWith("\"")) { +// requestBody = requestBody.substring(1, requestBody.length() - 1); +// } +// +// String decryptedBody; +// try { +// String providedHmac = exchange.getRequest().getHeaders().getFirst(HMAC_HEADER_NAME); +// integrityVerification(providedHmac, requestBody); +// decryptedBody = AesCbcUtils.decrypt(requestBody); +// } catch (Exception e) { +// log.error("解密请求体时发生错误: {}", e.getMessage(), e); +// exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); +// return exchange.getResponse().setComplete(); +// } +// +// DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory(); +// DataBuffer newBody = bufferFactory.wrap(decryptedBody.getBytes(StandardCharsets.UTF_8)); +// ServerHttpRequest newRequest = createNewRequest(exchange, newBody); +// +// return chain.filter(exchange.mutate().request(newRequest).build()); +// }); +// } +// +// private ServerHttpRequest createNewRequest(ServerWebExchange exchange, DataBuffer newBody) { +// return new ServerHttpRequestDecorator(exchange.getRequest()) { +// @Override +// public Flux getBody() { +// return Flux.just(newBody); +// } +// +// @Override +// public HttpHeaders getHeaders() { +// HttpHeaders headers = new HttpHeaders(); +// headers.putAll(exchange.getRequest().getHeaders()); +// headers.remove(HttpHeaders.CONTENT_LENGTH); +// headers.setContentLength(newBody.readableByteCount()); +// return headers; +// } +// }; +// } +// +// private ServerWebExchange updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException { +// ServerHttpRequest request = exchange.getRequest(); +// URI uri = request.getURI(); +// String query = uri.getQuery(); +// if (StringUtils.isNotBlank(query)) { +// String providedHmac = exchange.getRequest().getHeaders().getFirst(HMAC_HEADER_NAME); +// integrityVerification(providedHmac, query); +// String decryptedParam; +// try { +// decryptedParam = AesCbcUtils.decrypt(query); +// } catch (Exception e) { +// log.error("解密查询参数时发生错误: {}", e.getMessage(), e); +// throw new CaptchaException("请求参数不正确"); +// } +// if (StringUtils.isEmpty(decryptedParam)) { +// return null; +// } +// Map> queryParams = Arrays.stream(decryptedParam.split("&")) +// .map(param -> param.split("=")) +// .collect(Collectors.toMap( +// param -> param[0], +// param -> Collections.singletonList(param[1]) +// )); +// URI newUri = UriComponentsBuilder.fromUri(uri) +// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParams)) +// .build(true) +// .toUri(); +// +// ServerHttpRequest newRequest = request.mutate().uri(newUri).build(); +// +// return exchange.mutate().request(newRequest).build(); +// } +// return null; +// } +// +// /** +// * 数据完整性校验 +// * +// * @param providedHmac 请求头中的 HMAC 值 +// * @param query 请求参数 +// */ +// private void integrityVerification(String providedHmac, String query) { +// /* if (providedHmac == null) { +// log.error("请求头中缺少 Params-Hash"); +// throw new CaptchaException("请求参数不正确"); +// } +// String encrypt = Sm3Util.encrypt(query); +// log.debug("加密后的参数: {}", encrypt); +// log.debug("请求头中的 Params-Hash: {}", providedHmac); +// if (!encrypt.equals(providedHmac)) { +// log.error("参数校验失败"); +// throw new CaptchaException("请求参数不正确"); +// }*/ +// } +//} diff --git a/sql/bns_20240604.sql b/sql/bns_20240604.sql index f9bd6c9..2a8307f 100644 --- a/sql/bns_20240604.sql +++ b/sql/bns_20240604.sql @@ -717,30 +717,30 @@ create table gen_table_column ( primary key (column_id) ) engine=innodb auto_increment=1 comment = '代码生成业务表字段'; -drop table if exists `sys_logs`; -create table `sys_logs` ( - `log_id` varchar(80) NOT NULL COMMENT '主键', - `opera_user_name` varchar(30) NULL DEFAULT NULL, - `ip` varchar(30) NULL DEFAULT NULL COMMENT '操作ip', - `user_id` int NULL DEFAULT NULL COMMENT '操作人', - `model` varchar(200) NULL DEFAULT NULL COMMENT '操作模块', - `oper_time` varchar(50) NULL DEFAULT NULL COMMENT '操作时间', - `method` varchar(200) NULL DEFAULT NULL COMMENT '执行方法', - `params` varchar(4000) NULL DEFAULT NULL COMMENT '操作参数', - `operate_detail` varchar(500) NULL DEFAULT NULL COMMENT '操作详情', - `oper_type` varchar(20) NULL DEFAULT NULL COMMENT '操作类型 增删改查 登陆 登出', - `oper_uri` varchar(100) NULL DEFAULT NULL COMMENT '操作页面路径(uri', - `log_type` int NULL DEFAULT NULL COMMENT '日志类型 1 业务日志 0 系统日志 2异常日志', - `result` varchar(20) NULL DEFAULT NULL COMMENT '执行结果(成功/失败', - `times` varchar(30) NULL DEFAULT NULL COMMENT '执行时间(秒/ms)', - `failure_reason` varchar(3000) NULL DEFAULT NULL COMMENT '失败原因', - `grade` varchar(10) NULL DEFAULT NULL COMMENT '异常事件等级(高、中、低)', - `err_type` varchar(30) NULL DEFAULT NULL COMMENT '异常类型(ip异常/越权)', - `method_type` varchar(30) NULL DEFAULT NULL COMMENT '方法类型 POST/个体', - `title` varchar(255) NULL DEFAULT NULL, - `result_data` varchar(3000) NULL DEFAULT NULL COMMENT '返回数据', - PRIMARY KEY (`log_id`) USING BTREE -) engine = innodb comment = '系统日志表' ROW_FORMAT = Dynamic; +drop table if exists sys_logs; +create table sys_logs ( + log_id varchar(80) NOT NULL COMMENT '主键', + opera_user_name varchar(30) NULL DEFAULT NULL, + ip varchar(30) NULL DEFAULT NULL COMMENT '操作ip', + user_id int NULL DEFAULT NULL COMMENT '操作人', + model varchar(200) NULL DEFAULT NULL COMMENT '操作模块', + oper_time varchar(50) NULL DEFAULT NULL COMMENT '操作时间', + method varchar(200) NULL DEFAULT NULL COMMENT '执行方法', + params varchar(4000) NULL DEFAULT NULL COMMENT '操作参数', + operate_detail varchar(500) NULL DEFAULT NULL COMMENT '操作详情', + oper_type varchar(20) NULL DEFAULT NULL COMMENT '操作类型 增删改查 登陆 登出', + oper_uri varchar(100) NULL DEFAULT NULL COMMENT '操作页面路径(uri', + log_type int NULL DEFAULT NULL COMMENT '日志类型 1 业务日志 0 系统日志 2异常日志', + result varchar(20) NULL DEFAULT NULL COMMENT '执行结果(成功/失败', + times varchar(30) NULL DEFAULT NULL COMMENT '执行时间(秒/ms)', + failure_reason varchar(3000) NULL DEFAULT NULL COMMENT '失败原因', + grade varchar(10) NULL DEFAULT NULL COMMENT '异常事件等级(高、中、低)', + err_type varchar(30) NULL DEFAULT NULL COMMENT '异常类型(ip异常/越权)', + method_type varchar(30) NULL DEFAULT NULL COMMENT '方法类型 POST/个体', + title varchar(255) NULL DEFAULT NULL, + result_data varchar(3000) NULL DEFAULT NULL COMMENT '返回数据', + PRIMARY KEY (log_id) USING BTREE +) engine = innodb comment = '系统日志表' ; -- ---------------------------- -- Records of sys_logs @@ -749,12 +749,12 @@ create table `sys_logs` ( -- ---------------------------- -- Table structure for sys_logs_set -- ---------------------------- -drop table if exists `sys_logs_set`; -create table `sys_logs_set` ( -`capacity` varchar(255) NULL DEFAULT NULL +drop table if exists sys_logs_set; +create table sys_logs_set ( +capacity varchar(255) NULL DEFAULT NULL ) engine = innodb comment = '数据库日志容量设置表'; ; -- ---------------------------- -- Records of sys_logs_set -- ---------------------------- -insert into `sys_logs_set` values ('2048'); +insert into sys_logs_set values ('2048');