From ec9eb5a69ec245eeeac32684546298e5af1edbec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B7=E5=86=B7?= <2270033969@qq.com> Date: Thu, 9 Jan 2025 23:16:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(encrypt-api):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E8=AF=B7=E6=B1=82=E6=8A=A5=E6=96=87=E5=8A=A0?= =?UTF-8?q?=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: 文档和用法完全和之前不一样,不需要耦合代码 --- pigx-app-server/pigx-app-server-biz/pom.xml | 6 +- pigx-auth/pom.xml | 5 + .../core/constant/SecurityConstants.java | 370 +++++++++--------- .../encrypt/ApiEncryptAutoConfiguration.java | 39 +- .../api/encrypt/annotation/NoEncrypt.java | 16 + .../annotation/crypto/ApiCryptoAes.java | 22 -- .../annotation/crypto/ApiCryptoDes.java | 22 -- .../annotation/crypto/ApiCryptoRsa.java | 22 -- .../annotation/crypto/ApiCryptoSm4.java | 22 -- .../annotation/decrypt/ApiDecrypt.java | 40 -- .../annotation/decrypt/ApiDecryptAes.java | 36 -- .../annotation/decrypt/ApiDecryptDes.java | 33 -- .../annotation/decrypt/ApiDecryptRsa.java | 18 - .../annotation/decrypt/ApiDecryptSm4.java | 35 -- .../annotation/encrypt/ApiEncrypt.java | 34 -- .../annotation/encrypt/ApiEncryptAes.java | 29 -- .../annotation/encrypt/ApiEncryptDes.java | 29 -- .../annotation/encrypt/ApiEncryptRsa.java | 21 - .../annotation/encrypt/ApiEncryptSm4.java | 28 -- .../config/ApiEncryptParamConfiguration.java | 42 -- .../encrypt/config/ApiEncryptProperties.java | 97 +++-- .../encrypt/core/ApiDecryptParamResolver.java | 75 ---- .../core/ApiDecryptRequestBodyAdvice.java | 118 +++--- .../core/ApiEncryptResponseBodyAdvice.java | 89 +++-- .../core/DecryptQueryParametersFilter.java | 110 ++++++ .../core/DefaultSecretKeyResolver.java | 17 +- .../api/encrypt/core/ISecretKeyResolver.java | 3 +- .../api/encrypt/util/ApiCryptoUtil.java | 190 +++++---- .../PigxFeignInnerRequestInterceptor.java | 3 + pigx-upms/pigx-upms-biz/pom.xml | 5 + .../admin/controller/SysFileController.java | 3 + pigx-visual/pigx-codegen/pom.xml | 5 + .../controller/GeneratorController.java | 2 + pigx-visual/pigx-mp-platform/pom.xml | 5 + .../mp/controller/WxPortalController.java | 4 +- pigx-visual/pigx-pay-platform/pom.xml | 5 + .../controller/PayNotifyRecordController.java | 4 + .../pigx/pay/utils/RefundNameEnum.java | 39 +- 38 files changed, 678 insertions(+), 965 deletions(-) create mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/NoEncrypt.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoAes.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoDes.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoRsa.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoSm4.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecrypt.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptAes.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptDes.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptRsa.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptSm4.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncrypt.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptAes.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptDes.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptRsa.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptSm4.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptParamConfiguration.java delete mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptParamResolver.java create mode 100644 pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DecryptQueryParametersFilter.java diff --git a/pigx-app-server/pigx-app-server-biz/pom.xml b/pigx-app-server/pigx-app-server-biz/pom.xml index f06a38694..57f125bb9 100644 --- a/pigx-app-server/pigx-app-server-biz/pom.xml +++ b/pigx-app-server/pigx-app-server-biz/pom.xml @@ -62,7 +62,11 @@ com.pig4cloud pigx-app-server-api - 5.7.0 + + + + com.pig4cloud + pigx-common-encrypt-api diff --git a/pigx-auth/pom.xml b/pigx-auth/pom.xml index a492322ab..2dc08bd9e 100644 --- a/pigx-auth/pom.xml +++ b/pigx-auth/pom.xml @@ -83,6 +83,11 @@ cn.hutool hutool-crypto + + + com.pig4cloud + pigx-common-encrypt-api + io.springboot.plugin diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java index 33e0c783b..13e714ef1 100644 --- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java @@ -25,228 +25,238 @@ package com.pig4cloud.pigx.common.core.constant; */ public interface SecurityConstants { - /** - * 启动时是否检查Inner注解安全性 - */ - boolean INNER_CHECK = true; + /** + * 启动时是否检查Inner注解安全性 + */ + boolean INNER_CHECK = true; - /** - * 刷新 - */ - String REFRESH_TOKEN = "refresh_token"; + /** + * 刷新 + */ + String REFRESH_TOKEN = "refresh_token"; - /** - * 验证码有效期 - */ - int CODE_TIME = 60; + /** + * 验证码有效期 + */ + int CODE_TIME = 60; - /** - * 验证码长度 - */ - String CODE_SIZE = "4"; + /** + * 验证码长度 + */ + String CODE_SIZE = "4"; - /** - * 角色前缀 - */ - String ROLE = "ROLE_"; + /** + * 角色前缀 + */ + String ROLE = "ROLE_"; - /** - * 前缀 - */ - String PIGX_PREFIX = "pigx_"; + /** + * 前缀 + */ + String PIGX_PREFIX = "pigx_"; - /** - * token 相关前缀 - */ - String TOKEN_PREFIX = "token:"; + /** + * token 相关前缀 + */ + String TOKEN_PREFIX = "token:"; - /** - * oauth 相关前缀 - */ - String OAUTH_PREFIX = "oauth:"; + /** + * oauth 相关前缀 + */ + String OAUTH_PREFIX = "oauth:"; - /** - * 授权码模式code key 前缀 - */ - String OAUTH_CODE_PREFIX = "oauth:code:"; + /** + * 授权码模式code key 前缀 + */ + String OAUTH_CODE_PREFIX = "oauth:code:"; - /** - * 项目的license - */ - String PIGX_LICENSE = "https://pig4cloud.com"; + /** + * 项目的license + */ + String PIGX_LICENSE = "https://pig4cloud.com"; - /** - * 内部 - */ - String FROM_IN = "Y"; + /** + * 内部 + */ + String FROM_IN = "Y"; - /** - * 标志 - */ - String FROM = "from"; + /** + * 标志 + */ + String FROM = "from"; - /** - * 请求header - */ - String HEADER_FROM_IN = FROM + "=" + FROM_IN; + /** + * Feign 用户代理 + */ + String FEIGN_USER_AGENT = "pigx-feign"; - /** - * OAUTH URL - */ - String OAUTH_TOKEN_URL = "/oauth2/token"; + /** + * 请求header + */ + String HEADER_FROM_IN = FROM + "=" + FROM_IN; - /** - * 移动端授权 - */ - String GRANT_MOBILE = "mobile"; + /** + * OAUTH URL + */ + String OAUTH_TOKEN_URL = "/oauth2/token"; - /** - * TOC 客户端 - */ - String HEADER_TOC = "CLIENT-TOC"; + /** + * 移动端授权 + */ + String GRANT_MOBILE = "mobile"; - /** - * TOC 客户端 - */ - String HEADER_TOC_YES = "Y"; + /** + * TOC 客户端 + */ + String HEADER_TOC = "CLIENT-TOC"; - /** - * QQ获取token - */ - String QQ_AUTHORIZATION_CODE_URL = "https://graph.qq.com/oauth2.0/token?grant_type=" - + "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s"; + /** + * TOC 客户端 + */ + String HEADER_TOC_YES = "Y"; - /** - * 微信获取OPENID - */ - String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token" - + "?appid=%s&secret=%s&code=%s&grant_type=authorization_code"; + /** + * QQ获取token + */ + String QQ_AUTHORIZATION_CODE_URL = "https://graph.qq.com/oauth2.0/token?grant_type=" + + "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s"; - /** - * 微信小程序OPENID - */ - String MINI_APP_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/jscode2session" - + "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"; + /** + * 微信获取OPENID + */ + String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token" + + "?appid=%s&secret=%s&code=%s&grant_type=authorization_code"; - /** - * 码云获取token - */ - String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type=" - + "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s"; + /** + * 微信小程序OPENID + */ + String MINI_APP_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/jscode2session" + + "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"; - /** - * 开源中国获取token - */ - String OSC_AUTHORIZATION_CODE_URL = "https://www.oschina.net/action/openapi/token"; + /** + * 码云获取token + */ + String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type=" + + "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s"; - /** - * QQ获取用户信息 - */ - String QQ_USER_INFO_URL = "https://graph.qq.com/oauth2.0/me?access_token=%s"; + /** + * 开源中国获取token + */ + String OSC_AUTHORIZATION_CODE_URL = "https://www.oschina.net/action/openapi/token"; - /** - * 码云获取用户信息 - */ - String GITEE_USER_INFO_URL = "https://gitee.com/api/v5/user?access_token=%s"; + /** + * QQ获取用户信息 + */ + String QQ_USER_INFO_URL = "https://graph.qq.com/oauth2.0/me?access_token=%s"; - /** - * 开源中国用户信息 - */ - String OSC_USER_INFO_URL = "https://www.oschina.net/action/openapi/user?access_token=%s&dataType=json"; + /** + * 码云获取用户信息 + */ + String GITEE_USER_INFO_URL = "https://gitee.com/api/v5/user?access_token=%s"; - /** - * 钉钉获取 token - */ - String DING_OLD_GET_TOKEN = "https://oapi.dingtalk.com/gettoken"; + /** + * 开源中国用户信息 + */ + String OSC_USER_INFO_URL = "https://www.oschina.net/action/openapi/user?access_token=%s&dataType=json"; - /** - * 钉钉同步部门列表 - */ - String DING_OLD_DEPT_URL = "https://oapi.dingtalk.com/topapi/v2/department/listsub"; + /** + * 钉钉获取 token + */ + String DING_OLD_GET_TOKEN = "https://oapi.dingtalk.com/gettoken"; - /** - * 钉钉部门用户id列表 - */ - String DING_DEPT_USERIDS_URL = "https://oapi.dingtalk.com/topapi/user/listid"; + /** + * 钉钉同步部门列表 + */ + String DING_OLD_DEPT_URL = "https://oapi.dingtalk.com/topapi/v2/department/listsub"; - /** - * 钉钉用户详情 - */ - String DING_USER_INFO_URL = "https://oapi.dingtalk.com/topapi/v2/user/get"; + /** + * 钉钉部门用户id列表 + */ + String DING_DEPT_USERIDS_URL = "https://oapi.dingtalk.com/topapi/user/listid"; - /** - * {bcrypt} 加密的特征码 - */ - String BCRYPT = "{bcrypt}"; + /** + * 钉钉用户详情 + */ + String DING_USER_INFO_URL = "https://oapi.dingtalk.com/topapi/v2/user/get"; - /** - * 客户端模式 - */ - String CLIENT_CREDENTIALS = "client_credentials"; + /** + * {bcrypt} 加密的特征码 + */ + String BCRYPT = "{bcrypt}"; - /** - * 客户端编号 - */ - String CLIENT_ID = "client_id"; + /** + * 客户端模式 + */ + String CLIENT_CREDENTIALS = "client_credentials"; - /** - * 客户端唯一令牌 - */ - String CLIENT_RECREATE = "recreate_flag"; + /** + * 客户端编号 + */ + String CLIENT_ID = "client_id"; - /** - * 用户ID字段 - */ - String DETAILS_USER_ID = "user_id"; + /** + * 客户端唯一令牌 + */ + String CLIENT_RECREATE = "recreate_flag"; - /** - * 用户名 - */ - String DETAILS_USERNAME = "username"; + /** + * 用户ID字段 + */ + String DETAILS_USER_ID = "user_id"; - /** - * 姓名 - */ - String NAME = "name"; + /** + * 用户名 + */ + String DETAILS_USERNAME = "username"; - /** - * 协议字段 - */ - String DETAILS_LICENSE = "license"; + /** + * 姓名 + */ + String NAME = "name"; - /** - * 激活字段 兼容外围系统接入 - */ - String ACTIVE = "active"; + /** + * 协议字段 + */ + String DETAILS_LICENSE = "license"; - /** - * AES 加密 - */ - String AES = "aes"; + /** + * 激活字段 兼容外围系统接入 + */ + String ACTIVE = "active"; - /** - * 授权码模式confirm - */ - String CUSTOM_CONSENT_PAGE_URI = "/token/confirm_access"; + /** + * AES 加密 + */ + String AES = "aes"; - /** - * {noop} 加密的特征码 - */ - String NOOP = "{noop}"; + /** + * 授权码模式confirm + */ + String CUSTOM_CONSENT_PAGE_URI = "/oauth2/confirm_access"; - /** - * 短信登录 参数名称 - */ - String SMS_PARAMETER_NAME = "mobile"; + /** + * {noop} 加密的特征码 + */ + String NOOP = "{noop}"; - /** - * 手机号登录 - */ - String APP = "mobile"; + /** + * 短信登录 参数名称 + */ + String SMS_PARAMETER_NAME = "mobile"; - /** - * 用户信息 - */ - String DETAILS_USER = "user_info"; + /** + * 手机号登录 + */ + String APP = "mobile"; + + /** + * 用户信息 + */ + String DETAILS_USER = "user_info"; + + /** + * 不脱敏的权限 + */ + String NO_MASK = "no_mask"; } diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/ApiEncryptAutoConfiguration.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/ApiEncryptAutoConfiguration.java index a30402ee4..a823fbd6a 100644 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/ApiEncryptAutoConfiguration.java +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/ApiEncryptAutoConfiguration.java @@ -1,12 +1,8 @@ package com.pig4cloud.pigx.common.api.encrypt; import cn.hutool.crypto.SecureUtil; -import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptParamConfiguration; import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptProperties; -import com.pig4cloud.pigx.common.api.encrypt.core.ApiDecryptRequestBodyAdvice; -import com.pig4cloud.pigx.common.api.encrypt.core.ApiEncryptResponseBodyAdvice; -import com.pig4cloud.pigx.common.api.encrypt.core.DefaultSecretKeyResolver; -import com.pig4cloud.pigx.common.api.encrypt.core.ISecretKeyResolver; +import com.pig4cloud.pigx.common.api.encrypt.core.*; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -22,24 +18,25 @@ import org.springframework.context.annotation.Import; */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ApiEncryptProperties.class) -@Import({ ApiEncryptParamConfiguration.class, ApiDecryptRequestBodyAdvice.class, ApiEncryptResponseBodyAdvice.class }) -@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true", matchIfMissing = true) +@Import({DecryptQueryParametersFilter.class, ApiDecryptRequestBodyAdvice.class, ApiEncryptResponseBodyAdvice.class}) +@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true") public class ApiEncryptAutoConfiguration { - static { - // 关闭hutool 强制关闭Bouncy Castle库的依赖 - SecureUtil.disableBouncyCastle(); - } + static { + // 关闭hutool 强制关闭Bouncy Castle库的依赖 + SecureUtil.disableBouncyCastle(); + } - /** - * 默认的 key 获取策略 - * @param apiEncryptProperties - * @return - */ - @Bean - @ConditionalOnMissingBean - public ISecretKeyResolver secretKeyResolver(ApiEncryptProperties apiEncryptProperties) { - return new DefaultSecretKeyResolver(apiEncryptProperties); - } + /** + * 默认的 key 获取策略 + * + * @param apiEncryptProperties + * @return + */ + @Bean + @ConditionalOnMissingBean + public ISecretKeyResolver secretKeyResolver(ApiEncryptProperties apiEncryptProperties) { + return new DefaultSecretKeyResolver(apiEncryptProperties); + } } diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/NoEncrypt.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/NoEncrypt.java new file mode 100644 index 000000000..839a1f4a1 --- /dev/null +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/NoEncrypt.java @@ -0,0 +1,16 @@ +package com.pig4cloud.pigx.common.api.encrypt.annotation; + +import java.lang.annotation.*; + +/** + * 无加密配置注解 + * + * @author lengleng + * @date 2025/01/08 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface NoEncrypt { +} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoAes.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoAes.java deleted file mode 100644 index 383779f26..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoAes.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.crypto; - -import com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt.ApiDecrypt; -import com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt.ApiEncrypt; -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - * AES加密解密注解 - * - * @author Chill - */ -@Target({ ElementType.TYPE, ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -@ApiEncrypt(EncryptType.AES) -@ApiDecrypt(EncryptType.AES) -public @interface ApiCryptoAes { - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoDes.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoDes.java deleted file mode 100644 index a9586a3a8..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoDes.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.crypto; - -import com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt.ApiDecrypt; -import com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt.ApiEncrypt; -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - * DES加密解密注解 - * - * @author Chill - */ -@Target({ ElementType.TYPE, ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -@ApiEncrypt(EncryptType.DES) -@ApiDecrypt(EncryptType.DES) -public @interface ApiCryptoDes { - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoRsa.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoRsa.java deleted file mode 100644 index c4f4edf17..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoRsa.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.crypto; - -import com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt.ApiDecrypt; -import com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt.ApiEncrypt; -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - * RSA加密解密注解 - * - * @author Chill - */ -@Target({ ElementType.TYPE, ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -@ApiEncrypt(EncryptType.RSA) -@ApiDecrypt(EncryptType.RSA) -public @interface ApiCryptoRsa { - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoSm4.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoSm4.java deleted file mode 100644 index 75da031cb..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/crypto/ApiCryptoSm4.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.crypto; - -import com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt.ApiDecrypt; -import com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt.ApiEncrypt; -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - * Sm4加密解密注解 - * - * @author lengleng - */ -@Target({ ElementType.TYPE, ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -@ApiEncrypt(EncryptType.SM4) -@ApiDecrypt(EncryptType.SM4) -public @interface ApiCryptoSm4 { - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecrypt.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecrypt.java deleted file mode 100644 index a17d3c554..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecrypt.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - *

- * 解密含有{@link org.springframework.web.bind.annotation.RequestBody}注解的参数请求数据,可用于整个控制类或者某个控制器上 - *

- * - * @author licoy.cn - * @author L.cm - * @version 2018/9/7 - */ -@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -public @interface ApiDecrypt { - - /** - * 参数名称 仅针对GET请求有效 - * @return string - */ - String parameter() default ""; - - /** - * 解密类型 - * @return 类型 - */ - EncryptType value(); - - /** - * 私钥,用于某些需要单独配置私钥的方法,没有时读取全局配置的私钥 - * @return 私钥 - */ - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptAes.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptAes.java deleted file mode 100644 index 2b7be4a8e..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptAes.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; -import org.springframework.core.annotation.AliasFor; - -import java.lang.annotation.*; - -/** - * aes 界面 - * - * @author licoy.cn - * @author L.cm - * @version 2018/9/7 - * @see ApiDecrypt - */ -@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiDecrypt(EncryptType.AES) -public @interface ApiDecryptAes { - - /** - * 参数名称 仅针对GET请求有效 - * @return string - */ - @AliasFor(annotation = ApiDecrypt.class, attribute = "parameter") - String value() default ""; - - /** - * Alias for {@link ApiDecrypt#secretKey()}. - * @return {String} - */ - @AliasFor(annotation = ApiDecrypt.class) - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptDes.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptDes.java deleted file mode 100644 index 3c133c0d4..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptDes.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; -import org.springframework.core.annotation.AliasFor; - -import java.lang.annotation.*; - -/** - * @author licoy.cn - * @version 2018/9/7 - * @see ApiDecrypt - */ -@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiDecrypt(EncryptType.DES) -public @interface ApiDecryptDes { - - /** - * 参数名称 仅针对GET请求有效 - * @return string - */ - @AliasFor(annotation = ApiDecrypt.class, attribute = "parameter") - String value() default ""; - - /** - * Alias for {@link ApiDecrypt#secretKey()}. - * @return {String} - */ - @AliasFor(annotation = ApiDecrypt.class) - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptRsa.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptRsa.java deleted file mode 100644 index c5afdeafe..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptRsa.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - * @author licoy.cn - * @version 2018/9/7 - * @see ApiDecrypt - */ -@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiDecrypt(EncryptType.RSA) -public @interface ApiDecryptRsa { - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptSm4.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptSm4.java deleted file mode 100644 index 423e382c3..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/decrypt/ApiDecryptSm4.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; -import org.springframework.core.annotation.AliasFor; - -import java.lang.annotation.*; - -/** - * sm4 解密 - * - * @author lengleng - * @version 2023/8/30 - * @see ApiDecrypt - */ -@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiDecrypt(EncryptType.SM4) -public @interface ApiDecryptSm4 { - - /** - * 参数名称 仅针对GET请求有效 - * @return string - */ - @AliasFor(annotation = ApiDecrypt.class, attribute = "parameter") - String value() default ""; - - /** - * Alias for {@link ApiDecrypt#secretKey()}. - * @return {String} - */ - @AliasFor(annotation = ApiDecrypt.class) - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncrypt.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncrypt.java deleted file mode 100644 index b6ac3197e..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncrypt.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - *

- * 加密{@link org.springframework.web.bind.annotation.ResponseBody}响应数据,可用于整个控制类或者某个控制器上 - *

- * - * @author licoy.cn - * @author L.cm - * @version 2018/9/4 - */ -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -public @interface ApiEncrypt { - - /** - * 加密类型 - * @return 类型 - */ - EncryptType value(); - - /** - * 私钥,用于某些需要单独配置私钥的方法,没有时读取全局配置的私钥 - * @return 私钥 - */ - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptAes.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptAes.java deleted file mode 100644 index 9ff3e5e5e..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptAes.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; -import org.springframework.core.annotation.AliasFor; - -import java.lang.annotation.*; - -/** - * aes 加密 - * - * @author licoy.cn - * @author L.cm - * @version 2018/9/4 - * @see ApiEncrypt - */ -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiEncrypt(EncryptType.AES) -public @interface ApiEncryptAes { - - /** - * Alias for {@link ApiEncrypt#secretKey()}. - * @return {String} - */ - @AliasFor(annotation = ApiEncrypt.class) - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptDes.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptDes.java deleted file mode 100644 index 11dd120fe..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptDes.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; -import org.springframework.core.annotation.AliasFor; - -import java.lang.annotation.*; - -/** - * des 加密 - * - * @author licoy.cn - * @author L.cm - * @version 2018/9/4 - * @see ApiEncrypt - */ -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiEncrypt(EncryptType.DES) -public @interface ApiEncryptDes { - - /** - * Alias for {@link ApiEncrypt#secretKey()}. - * @return {String} - */ - @AliasFor(annotation = ApiEncrypt.class) - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptRsa.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptRsa.java deleted file mode 100644 index b4186c6b0..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptRsa.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import java.lang.annotation.*; - -/** - * rsa body 加密 - * - * @author licoy.cn - * @author L.cm - * @version 2018/9/4 - * @see ApiEncrypt - */ -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiEncrypt(EncryptType.RSA) -public @interface ApiEncryptRsa { - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptSm4.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptSm4.java deleted file mode 100644 index 8480acf24..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/annotation/encrypt/ApiEncryptSm4.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt; - -import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; -import org.springframework.core.annotation.AliasFor; - -import java.lang.annotation.*; - -/** - * sm4 加密 - * - * @author lengleng - * @version 2023/8/30 - * @see ApiEncrypt - */ -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@ApiEncrypt(EncryptType.SM4) -public @interface ApiEncryptSm4 { - - /** - * Alias for {@link ApiEncrypt#secretKey()}. - * @return {String} - */ - @AliasFor(annotation = ApiEncrypt.class) - String secretKey() default ""; - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptParamConfiguration.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptParamConfiguration.java deleted file mode 100644 index 510ce0176..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptParamConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net). - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pig4cloud.pigx.common.api.encrypt.config; - -import com.pig4cloud.pigx.common.api.encrypt.core.ApiDecryptParamResolver; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import java.util.List; - -/** - * api 签名自动配置 - * - * @author L.cm - */ -@RequiredArgsConstructor -@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true", matchIfMissing = true) -public class ApiEncryptParamConfiguration implements WebMvcConfigurer { - - private final ApiEncryptProperties apiEncryptProperties; - - public void addArgumentResolvers(List argumentResolvers) { - argumentResolvers.add(new ApiDecryptParamResolver(apiEncryptProperties)); - } - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptProperties.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptProperties.java index 8e2733bc7..36fa1b7fa 100644 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptProperties.java +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/config/ApiEncryptProperties.java @@ -1,8 +1,18 @@ package com.pig4cloud.pigx.common.api.encrypt.config; +import com.pig4cloud.pigx.common.api.encrypt.annotation.NoEncrypt; +import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; +import com.pig4cloud.pigx.common.core.util.SpringContextHolder; import lombok.Getter; import lombok.Setter; +import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.util.*; /** * api 签名配置类 @@ -14,46 +24,67 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @Getter @Setter @ConfigurationProperties(ApiEncryptProperties.PREFIX) -public class ApiEncryptProperties { +public class ApiEncryptProperties implements InitializingBean { - /** - * 前缀 - */ - public static final String PREFIX = "security.api.encrypt"; + /** + * 前缀 + */ + public static final String PREFIX = "security.api.encrypt"; - /** - * 是否开启 api 签名 - */ - private boolean enable = true; + /** + * 是否开启 api 签名 + */ + private boolean enable; - /** - * url的参数签名,传递的参数名。例如:/user?data=签名后的数据 - */ - private String paramName = "encryption"; + /** + * body 内容 json key, 默认:encryption + */ + private String bodyJsonKey = "encryption"; - /** - * body 内容 json key, 默认:encryption - */ - private String bodyJsonKey = "encryption"; + /** + * 默认加密类型 + */ + private EncryptType defaultEncryptType = EncryptType.AES; - /** - * aes 密钥 - */ - private String aesKey; + /** + * aes 密钥 + */ + private String aesKey; - /** - * des 密钥 - */ - private String desKey; + /** + * des 密钥 + */ + private String desKey; - /** - * sm4 密钥 - */ - private String sm4Key; + /** + * sm4 密钥 + */ + private String sm4Key; - /** - * rsa 私钥 - */ - private String rsaPrivateKey; + /** + * rsa 私钥 + */ + private String rsaPrivateKey; + + /** + * 跳过 URL + */ + private List skipUrl = new ArrayList<>(); + + @Override + public void afterPropertiesSet() throws Exception { + RequestMappingHandlerMapping mapping = SpringContextHolder.getBean("requestMappingHandlerMapping"); + Map map = mapping.getHandlerMethods(); + + map.keySet().forEach(info -> { + HandlerMethod handlerMethod = map.get(info); + + // 获取方法上边的注解 替代path variable 为 * + NoEncrypt method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), NoEncrypt.class); + Optional.ofNullable(method) + .ifPresent(inner -> skipUrl.addAll(Objects.requireNonNull(info.getPathPatternsCondition()) + .getPatternValues())); + }); + } } diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptParamResolver.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptParamResolver.java deleted file mode 100644 index 277c0d436..000000000 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptParamResolver.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net). - *

- * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.gnu.org/licenses/lgpl.html - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pig4cloud.pigx.common.api.encrypt.core; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt.ApiDecrypt; -import com.pig4cloud.pigx.common.api.encrypt.bean.CryptoInfoBean; -import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptProperties; -import com.pig4cloud.pigx.common.api.encrypt.util.ApiCryptoUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.core.MethodParameter; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.lang.Nullable; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -import java.lang.reflect.Parameter; -import java.nio.charset.StandardCharsets; - -/** - * param 参数 解析 - * - * @author L.cm - */ -@RequiredArgsConstructor -public class ApiDecryptParamResolver implements HandlerMethodArgumentResolver { - - private final ApiEncryptProperties properties; - - @Override - public boolean supportsParameter(MethodParameter parameter) { - return AnnotatedElementUtils.hasAnnotation(parameter.getParameter(), ApiDecrypt.class); - } - - @Nullable - @Override - public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { - Parameter parameter = methodParameter.getParameter(); - ApiDecrypt apiDecrypt = AnnotatedElementUtils.getMergedAnnotation(parameter, ApiDecrypt.class); - - if (StrUtil.isBlank(apiDecrypt.parameter())) { - return null; - } - - String text = webRequest.getParameter(properties.getParamName()); - if (StrUtil.isBlank(text)) { - return null; - } - CryptoInfoBean infoBean = new CryptoInfoBean(apiDecrypt.value(), apiDecrypt.secretKey()); - byte[] textBytes = text.getBytes(StandardCharsets.UTF_8); - byte[] decryptData = ApiCryptoUtil.decryptData(textBytes, infoBean); - JSONObject jsonObject = JSONUtil.parseObj(decryptData); - return jsonObject.get(apiDecrypt.parameter(), parameter.getType()); - } - -} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptRequestBodyAdvice.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptRequestBodyAdvice.java index 0da2f1467..4531e4af9 100644 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptRequestBodyAdvice.java +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiDecryptRequestBodyAdvice.java @@ -3,12 +3,14 @@ package com.pig4cloud.pigx.common.api.encrypt.core; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.util.StrUtil; import com.fasterxml.jackson.databind.ObjectMapper; -import com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt.ApiDecrypt; +import com.pig4cloud.pigx.common.api.encrypt.annotation.NoEncrypt; import com.pig4cloud.pigx.common.api.encrypt.bean.CryptoInfoBean; import com.pig4cloud.pigx.common.api.encrypt.bean.DecryptHttpInputMessage; import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptProperties; import com.pig4cloud.pigx.common.api.encrypt.exception.DecryptBodyFailException; import com.pig4cloud.pigx.common.api.encrypt.util.ApiCryptoUtil; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.util.WebUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -27,6 +29,8 @@ import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.util.Map; +import static com.pig4cloud.pigx.common.api.encrypt.util.ApiCryptoUtil.KEY_EXTRACTORS; + /** * 请求数据的加密信息解密处理
* 本类只对控制器参数中含有{@link org.springframework.web.bind.annotation.RequestBody} @@ -41,68 +45,74 @@ import java.util.Map; @Order(1) @ControllerAdvice @RequiredArgsConstructor -@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true", matchIfMissing = true) +@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true") public class ApiDecryptRequestBodyAdvice implements RequestBodyAdvice { - private final ApiEncryptProperties properties; + private final ApiEncryptProperties properties; - private final ObjectMapper objectMapper; + private final ObjectMapper objectMapper; - @Override - public boolean supports(MethodParameter methodParameter, Type targetType, - Class> converterType) { - return AnnotationUtil.hasAnnotation(methodParameter.getMethod(), ApiDecrypt.class); - } + @Override + public boolean supports(MethodParameter methodParameter, Type targetType, + Class> converterType) { + // 非feign调用才进行解密 + if (StrUtil.isNotBlank(WebUtils.getRequest().getHeader(SecurityConstants.FEIGN_USER_AGENT))) { + return false; + } - @Override - public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, - Type targetType, Class> converterType) { - return body; - } + if (AnnotationUtil.hasAnnotation(methodParameter.getMethod(), NoEncrypt.class)) { + return false; + } - @Override - public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, - Class> converterType) throws IOException { - // 判断 body 是否为空 - InputStream messageBody = inputMessage.getBody(); - if (messageBody.available() <= 0) { - return inputMessage; - } + return properties.getSkipUrl().stream().noneMatch(WebUtils.getRequest().getRequestURI()::contains); + } - CryptoInfoBean cryptoInfoBean = ApiCryptoUtil.getDecryptInfo(parameter); - if (cryptoInfoBean == null) { - throw new DecryptBodyFailException("获取解密注解配置为空"); - } - // base64 byte array - byte[] bodyByteArray = StreamUtils.copyToByteArray(messageBody); - // body 内容 json key, 默认:data {"data":"base64加密字符串"} - String bodyJsonKey = properties.getBodyJsonKey(); + @Override + public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, + Type targetType, Class> converterType) { + return body; + } - byte[] decryptedBody = null; - if (StrUtil.isBlank(bodyJsonKey)) { - decryptedBody = ApiCryptoUtil.decryptData(bodyByteArray, cryptoInfoBean); - } - else { + @Override + public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, + Class> converterType) throws IOException { + // 判断 body 是否为空 + InputStream messageBody = inputMessage.getBody(); + if (messageBody.available() <= 0) { + return inputMessage; + } - Map data = objectMapper.readValue(bodyByteArray, Map.class); - String content = (String) data.get(bodyJsonKey); - if (content != null) { - decryptedBody = ApiCryptoUtil.decryptData(content.getBytes(StandardCharsets.UTF_8), cryptoInfoBean); - } - } - if (decryptedBody == null) { - throw new DecryptBodyFailException( - "Decryption error, " + "please check if the selected source data is encrypted correctly." - + " (解密错误,请检查选择的源数据的加密方式是否正确。)"); - } - InputStream inputStream = new ByteArrayInputStream(decryptedBody); - return new DecryptHttpInputMessage(inputStream, inputMessage.getHeaders()); - } + String key = KEY_EXTRACTORS.get(properties.getDefaultEncryptType()).apply(properties); + CryptoInfoBean cryptoInfoBean = new CryptoInfoBean(properties.getDefaultEncryptType(), key); + // base64 byte array + byte[] bodyByteArray = StreamUtils.copyToByteArray(messageBody); + // body 内容 json key, 默认:data {"data":"base64加密字符串"} + String bodyJsonKey = properties.getBodyJsonKey(); - @Override - public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, - Class> converterType) { - return body; - } + byte[] decryptedBody = null; + if (StrUtil.isBlank(bodyJsonKey)) { + decryptedBody = ApiCryptoUtil.decryptData(bodyByteArray, cryptoInfoBean); + } else { + + Map data = objectMapper.readValue(bodyByteArray, Map.class); + String content = (String) data.get(bodyJsonKey); + if (content != null) { + decryptedBody = ApiCryptoUtil.decryptData(content.getBytes(StandardCharsets.UTF_8), cryptoInfoBean); + } + } + if (decryptedBody == null) { + throw new DecryptBodyFailException( + "Decryption error, " + "please check if the selected source data is encrypted correctly." + + " (解密错误,请检查选择的源数据的加密方式是否正确。)"); + } + InputStream inputStream = new ByteArrayInputStream(decryptedBody); + return new DecryptHttpInputMessage(inputStream, inputMessage.getHeaders()); + } + + @Override + public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, + Class> converterType) { + return body; + } } diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiEncryptResponseBodyAdvice.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiEncryptResponseBodyAdvice.java index 00fab9fe6..cfe84b671 100644 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiEncryptResponseBodyAdvice.java +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ApiEncryptResponseBodyAdvice.java @@ -4,11 +4,12 @@ import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.util.StrUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt.ApiEncrypt; +import com.pig4cloud.pigx.common.api.encrypt.annotation.NoEncrypt; import com.pig4cloud.pigx.common.api.encrypt.bean.CryptoInfoBean; import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptProperties; -import com.pig4cloud.pigx.common.api.encrypt.exception.EncryptBodyFailException; import com.pig4cloud.pigx.common.api.encrypt.util.ApiCryptoUtil; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.util.WebUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -19,10 +20,16 @@ import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; +import java.io.InputStream; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Objects; + +import static com.pig4cloud.pigx.common.api.encrypt.util.ApiCryptoUtil.KEY_EXTRACTORS; /** * 响应数据的加密处理
@@ -39,47 +46,57 @@ import java.util.Map; @Order(1) @ControllerAdvice @RequiredArgsConstructor -@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true", matchIfMissing = true) +@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true") public class ApiEncryptResponseBodyAdvice implements ResponseBodyAdvice { - private final ApiEncryptProperties properties; + private final ApiEncryptProperties properties; - private final ObjectMapper objectMapper; + private final ObjectMapper objectMapper; - @Override - public boolean supports(MethodParameter returnType, Class converterType) { - return AnnotationUtil.hasAnnotation(returnType.getMethod(), ApiEncrypt.class); - } + @Override + public boolean supports(MethodParameter methodParameter, Class converterType) { - @Nullable - @Override - public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, - Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { - if (body == null) { - return null; - } + // 非feign调用才进行加密 + if (StrUtil.isNotBlank(WebUtils.getRequest().getHeader(SecurityConstants.FEIGN_USER_AGENT))) { + return false; + } - CryptoInfoBean cryptoInfoBean = ApiCryptoUtil.getEncryptInfo(returnType); - if (cryptoInfoBean == null) { - throw new EncryptBodyFailException(); - } + // 上传文件的请求不加密,因为 element 的组件,需要自己定义HTTP ,不能使用全局 http 加密工具解析 + if (Arrays.stream(Objects.requireNonNull(methodParameter.getMethod()).getParameterTypes()) + .anyMatch(type -> MultipartFile.class.isAssignableFrom(type) || InputStream.class.isAssignableFrom(type))) { + return false; + } - byte[] bodyJsonBytes; - try { - bodyJsonBytes = objectMapper.writeValueAsBytes(body); - } - catch (JsonProcessingException e) { - throw new RuntimeException(e); - } + if (AnnotationUtil.hasAnnotation(methodParameter.getMethod(), NoEncrypt.class)) { + return false; + } - // body 内容 json key, 默认:data {"data":"base64加密字符串"} - String bodyJsonKey = properties.getBodyJsonKey(); - if (StrUtil.isBlank(bodyJsonKey)) { - return ApiCryptoUtil.encryptData(bodyJsonBytes, cryptoInfoBean); - } - Map data = new HashMap<>(2); - data.put(bodyJsonKey, ApiCryptoUtil.encryptData(bodyJsonBytes, cryptoInfoBean)); - return data; - } + return properties.getSkipUrl().stream().noneMatch(WebUtils.getRequest().getRequestURI()::contains); + } + + @Nullable + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, + Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + + String key = KEY_EXTRACTORS.get(properties.getDefaultEncryptType()).apply(properties); + CryptoInfoBean cryptoInfoBean = new CryptoInfoBean(properties.getDefaultEncryptType(), key); + + byte[] bodyJsonBytes; + try { + bodyJsonBytes = objectMapper.writeValueAsBytes(body); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + // body 内容 json key, 默认:data {"data":"base64加密字符串"} + String bodyJsonKey = properties.getBodyJsonKey(); + if (StrUtil.isBlank(bodyJsonKey)) { + return ApiCryptoUtil.encryptData(bodyJsonBytes, cryptoInfoBean); + } + Map data = new HashMap<>(2); + data.put(bodyJsonKey, ApiCryptoUtil.encryptData(bodyJsonBytes, cryptoInfoBean)); + return data; + } } diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DecryptQueryParametersFilter.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DecryptQueryParametersFilter.java new file mode 100644 index 000000000..3fdcfed93 --- /dev/null +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DecryptQueryParametersFilter.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.common.api.encrypt.core; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; +import com.pig4cloud.pigx.common.api.encrypt.bean.CryptoInfoBean; +import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptProperties; +import com.pig4cloud.pigx.common.api.encrypt.util.ApiCryptoUtil; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.util.RepeatBodyRequestWrapper; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.Ordered; +import org.springframework.http.HttpMethod; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.Map; + +import static com.pig4cloud.pigx.common.api.encrypt.util.ApiCryptoUtil.KEY_EXTRACTORS; + +/** + * 解密GET查询参数 + * + * @author lengleng + * @date 2025/01/08 + */ +@Slf4j +@RequiredArgsConstructor +@ConditionalOnProperty(value = ApiEncryptProperties.PREFIX + ".enable", havingValue = "true") +public class DecryptQueryParametersFilter extends OncePerRequestFilter implements Ordered { + + private final ApiEncryptProperties encryptProperties; + + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + // 是否支持解密 + if (!supportDecrypt(request)) { + filterChain.doFilter(request, response); + return; + } + + Map parameterMap = request.getParameterMap(); + if (MapUtil.isEmpty(parameterMap)) { + filterChain.doFilter(request, response); + return; + } + + // 将请求流转换为可多次读取的请求流 + RepeatBodyRequestWrapper requestWrapper = new RepeatBodyRequestWrapper(request); + // 构建前端对应解密AES 因子 + parameterMap.forEach((k, v) -> { + String[] values = parameterMap.get(k); + if (ArrayUtil.isEmpty(values)) { + return; + } + + String key = KEY_EXTRACTORS.get(encryptProperties.getDefaultEncryptType()).apply(encryptProperties); + CryptoInfoBean cryptoInfoBean = new CryptoInfoBean(encryptProperties.getDefaultEncryptType(), key); + // 解密并覆盖原有值 + String decryptData = ApiCryptoUtil.decryptData(URLUtil.decode(values[0]), cryptoInfoBean); + parameterMap.put(k, new String[]{decryptData}); + }); + + requestWrapper.setParameterMap(parameterMap); + filterChain.doFilter(requestWrapper, response); + } + + /** + * 支持 Decrypt 解密 1. 开启了加密 2. 非 feign 请求 3. GET 方法 + * + * @param request 请求 + * @return boolean + */ + private boolean supportDecrypt(HttpServletRequest request) { + return encryptProperties.isEnable() + && encryptProperties.getSkipUrl().stream().noneMatch(request.getRequestURI()::contains) + && StrUtil.equalsAnyIgnoreCase(request.getMethod(), HttpMethod.GET.name()) + && StrUtil.isBlank(request.getHeader(SecurityConstants.FEIGN_USER_AGENT)); + } +} diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DefaultSecretKeyResolver.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DefaultSecretKeyResolver.java index 54705382a..655742d76 100644 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DefaultSecretKeyResolver.java +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/DefaultSecretKeyResolver.java @@ -2,10 +2,9 @@ package com.pig4cloud.pigx.common.api.encrypt.core; import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptProperties; import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import javax.servlet.http.HttpServletRequest; - /** * 默认的密钥处理器 * @@ -18,14 +17,12 @@ public class DefaultSecretKeyResolver implements ISecretKeyResolver { @Override public String getSecretKey(HttpServletRequest request, EncryptType encryptType) { - switch (encryptType) { - case DES: - return properties.getDesKey(); - case RSA: - return properties.getRsaPrivateKey(); - default: - return properties.getAesKey(); - } + return switch (encryptType) { + case SM4 -> properties.getSm4Key(); + case DES -> properties.getDesKey(); + case RSA -> properties.getRsaPrivateKey(); + default -> properties.getAesKey(); + }; } } diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ISecretKeyResolver.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ISecretKeyResolver.java index 0dd9cc5a2..6d15268c1 100644 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ISecretKeyResolver.java +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/core/ISecretKeyResolver.java @@ -1,8 +1,7 @@ package com.pig4cloud.pigx.common.api.encrypt.core; import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; - -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; /** * 解析加密密钥 diff --git a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/util/ApiCryptoUtil.java b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/util/ApiCryptoUtil.java index cebf6a5e1..a0883ee7b 100644 --- a/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/util/ApiCryptoUtil.java +++ b/pigx-common/pigx-common-encrypt-api/src/main/java/com/pig4cloud/pigx/common/api/encrypt/util/ApiCryptoUtil.java @@ -8,9 +8,8 @@ import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.symmetric.AES; -import com.pig4cloud.pigx.common.api.encrypt.annotation.decrypt.ApiDecrypt; -import com.pig4cloud.pigx.common.api.encrypt.annotation.encrypt.ApiEncrypt; import com.pig4cloud.pigx.common.api.encrypt.bean.CryptoInfoBean; +import com.pig4cloud.pigx.common.api.encrypt.config.ApiEncryptProperties; import com.pig4cloud.pigx.common.api.encrypt.core.ISecretKeyResolver; import com.pig4cloud.pigx.common.api.encrypt.enums.EncryptType; import com.pig4cloud.pigx.common.api.encrypt.exception.EncryptBodyFailException; @@ -18,15 +17,14 @@ import com.pig4cloud.pigx.common.api.encrypt.exception.EncryptMethodNotFoundExce import com.pig4cloud.pigx.common.core.util.SpringContextHolder; import com.pig4cloud.pigx.common.core.util.WebUtils; import lombok.experimental.UtilityClass; -import org.springframework.core.MethodParameter; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.function.Function; /** *

@@ -40,116 +38,104 @@ import java.nio.charset.StandardCharsets; @UtilityClass public class ApiCryptoUtil { - /** - * 获取方法控制器上的加密注解信息 - * @param methodParameter 控制器方法 - * @return 加密注解信息 - */ - @Nullable - public static CryptoInfoBean getEncryptInfo(MethodParameter methodParameter) { - ApiEncrypt encryptBody = AnnotatedElementUtils.findMergedAnnotation(methodParameter.getMethod(), - ApiEncrypt.class); - if (encryptBody == null) { - return null; - } - return new CryptoInfoBean(encryptBody.value(), encryptBody.secretKey()); - } + /** + * 密钥提取器 + */ + public static final Map> KEY_EXTRACTORS = Map.of( + EncryptType.AES, ApiEncryptProperties::getAesKey, + EncryptType.RSA, ApiEncryptProperties::getRsaPrivateKey, + EncryptType.DES, ApiEncryptProperties::getDesKey, + EncryptType.SM4, ApiEncryptProperties::getSm4Key + ); - /** - * 获取方法控制器上的解密注解信息 - * @param methodParameter 控制器方法 - * @return 加密注解信息 - */ - @Nullable - public static CryptoInfoBean getDecryptInfo(MethodParameter methodParameter) { - ApiDecrypt decryptBody = AnnotatedElementUtils.findMergedAnnotation(methodParameter.getMethod(), - ApiDecrypt.class); - if (decryptBody == null) { - return null; - } - return new CryptoInfoBean(decryptBody.value(), decryptBody.secretKey()); - } - /** - * 选择加密方式并进行加密 - * @param jsonData json 数据 - * @param infoBean 加密信息 - * @return 加密结果 - */ - public static String encryptData(byte[] jsonData, CryptoInfoBean infoBean) { - EncryptType type = infoBean.getType(); - if (type == null) { - throw new EncryptMethodNotFoundException(); - } + /** + * 选择加密方式并进行加密 + * + * @param jsonData json 数据 + * @param infoBean 加密信息 + * @return 加密结果 + */ + public static String encryptData(byte[] jsonData, CryptoInfoBean infoBean) { + EncryptType type = infoBean.getType(); + if (type == null) { + throw new EncryptMethodNotFoundException(); + } - String secretKey = infoBean.getSecretKey(); - if (StrUtil.isBlank(secretKey)) { - secretKey = SpringContextHolder.getBean(ISecretKeyResolver.class).getSecretKey(WebUtils.getRequest(), type); - } - Assert.hasText(secretKey, type + " key is not configured (未配置" + type + ")"); + String secretKey = infoBean.getSecretKey(); + if (StrUtil.isBlank(secretKey)) { + secretKey = SpringContextHolder.getBean(ISecretKeyResolver.class).getSecretKey(WebUtils.getRequest(), type); + } + Assert.hasText(secretKey, type + " key is not configured (未配置" + type + ")"); - if (type == EncryptType.DES) { + if (type == EncryptType.DES) { - return SecureUtil.des(secretKey.getBytes(StandardCharsets.UTF_8)).encryptBase64(jsonData); - } - if (type == EncryptType.AES) { - // 构建前端对应解密AES 因子 - AES aes = new AES(Mode.CFB, Padding.NoPadding, new SecretKeySpec(secretKey.getBytes(), "AES"), - new IvParameterSpec(secretKey.getBytes())); + return SecureUtil.des(secretKey.getBytes(StandardCharsets.UTF_8)).encryptBase64(jsonData); + } + if (type == EncryptType.AES) { + // 构建前端对应解密AES 因子 + AES aes = new AES(Mode.CFB, Padding.NoPadding, new SecretKeySpec(secretKey.getBytes(), "AES"), + new IvParameterSpec(secretKey.getBytes())); - return aes.encryptBase64(jsonData); - } - if (type == EncryptType.RSA) { - return SecureUtil.rsa(secretKey.getBytes(StandardCharsets.UTF_8), null).encryptBase64(jsonData, - KeyType.PrivateKey); - } + return aes.encryptBase64(jsonData); + } + if (type == EncryptType.RSA) { + return SecureUtil.rsa(secretKey.getBytes(StandardCharsets.UTF_8), null) + .encryptBase64(jsonData, KeyType.PrivateKey); + } - if (type == EncryptType.SM4) { - return SmUtil.sm4(HexUtil.decodeHex(secretKey)).encryptHex(jsonData); - } - throw new EncryptBodyFailException(); - } + if (type == EncryptType.SM4) { + return SmUtil.sm4(HexUtil.decodeHex(secretKey)).encryptHex(jsonData); + } + throw new EncryptBodyFailException(); + } - /** - * 选择加密方式并进行解密 - * @param bodyData byte array - * @param infoBean 加密信息 - * @return 解密结果 - */ - public static byte[] decryptData(byte[] bodyData, CryptoInfoBean infoBean) { - EncryptType type = infoBean.getType(); - if (type == null) { - throw new EncryptMethodNotFoundException(); - } + /** + * 选择加密方式并进行解密 + * + * @param bodyData byte array + * @param infoBean 加密信息 + * @return 解密结果 + */ + public static byte[] decryptData(byte[] bodyData, CryptoInfoBean infoBean) { + EncryptType type = infoBean.getType(); + if (type == null) { + throw new EncryptMethodNotFoundException(); + } - String secretKey = infoBean.getSecretKey(); - if (StrUtil.isBlank(secretKey)) { - secretKey = SpringContextHolder.getBean(ISecretKeyResolver.class).getSecretKey(WebUtils.getRequest(), type); - } - Assert.hasText(secretKey, type + " key is not configured (未配置" + type + ")"); + String secretKey = infoBean.getSecretKey(); + if (StrUtil.isBlank(secretKey)) { + secretKey = SpringContextHolder.getBean(ISecretKeyResolver.class).getSecretKey(WebUtils.getRequest(), type); + } + Assert.hasText(secretKey, type + " key is not configured (未配置" + type + ")"); - if (type == EncryptType.AES) { + if (type == EncryptType.AES) { - AES aes = new AES(Mode.CFB, Padding.NoPadding, - new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES"), - new IvParameterSpec(secretKey.getBytes(StandardCharsets.UTF_8))); - return aes.decrypt(StrUtil.str(bodyData, StandardCharsets.UTF_8)); + AES aes = new AES(Mode.CFB, Padding.NoPadding, + new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES"), + new IvParameterSpec(secretKey.getBytes(StandardCharsets.UTF_8))); + return aes.decrypt(StrUtil.str(bodyData, StandardCharsets.UTF_8)); - } - if (type == EncryptType.DES) { - return SecureUtil.des(secretKey.getBytes(StandardCharsets.UTF_8)).decrypt(bodyData); - } - if (type == EncryptType.RSA) { - return SecureUtil.rsa(secretKey.getBytes(StandardCharsets.UTF_8), null).decrypt(bodyData, - KeyType.PrivateKey); - } + } + if (type == EncryptType.DES) { + return SecureUtil.des(secretKey.getBytes(StandardCharsets.UTF_8)).decrypt(bodyData); + } + if (type == EncryptType.RSA) { + return SecureUtil.rsa(secretKey.getBytes(StandardCharsets.UTF_8), null) + .decrypt(bodyData, KeyType.PrivateKey); + } - if (type == EncryptType.SM4) { - return SmUtil.sm4(HexUtil.decodeHex(secretKey)).decryptStr(StrUtil.str(bodyData, Charset.defaultCharset())) - .getBytes(); - } + if (type == EncryptType.SM4) { + return SmUtil.sm4(HexUtil.decodeHex(secretKey)) + .decryptStr(StrUtil.str(bodyData, Charset.defaultCharset())) + .getBytes(); + } - throw new EncryptMethodNotFoundException(); - } + throw new EncryptMethodNotFoundException(); + } + + public static String decryptData(String bodyData, CryptoInfoBean infoBean) { + return StrUtil.str(decryptData(bodyData.getBytes(StandardCharsets.UTF_8), infoBean), StandardCharsets.UTF_8); + } } diff --git a/pigx-common/pigx-common-feign/src/main/java/com/pig4cloud/pigx/common/feign/interceptor/PigxFeignInnerRequestInterceptor.java b/pigx-common/pigx-common-feign/src/main/java/com/pig4cloud/pigx/common/feign/interceptor/PigxFeignInnerRequestInterceptor.java index d16cf75b0..5db2d61cb 100644 --- a/pigx-common/pigx-common-feign/src/main/java/com/pig4cloud/pigx/common/feign/interceptor/PigxFeignInnerRequestInterceptor.java +++ b/pigx-common/pigx-common-feign/src/main/java/com/pig4cloud/pigx/common/feign/interceptor/PigxFeignInnerRequestInterceptor.java @@ -26,6 +26,9 @@ public class PigxFeignInnerRequestInterceptor implements RequestInterceptor, Ord if (noToken != null) { template.header(SecurityConstants.FROM, SecurityConstants.FROM_IN); } + + // 从内部调用标识 + template.header(SecurityConstants.FEIGN_USER_AGENT, SecurityConstants.FROM_IN); } @Override diff --git a/pigx-upms/pigx-upms-biz/pom.xml b/pigx-upms/pigx-upms-biz/pom.xml index 8b1bf3d7d..9c762f508 100644 --- a/pigx-upms/pigx-upms-biz/pom.xml +++ b/pigx-upms/pigx-upms-biz/pom.xml @@ -126,6 +126,11 @@ com.pig4cloud pigx-common-gray + + + com.pig4cloud + pigx-common-encrypt-api + com.baomidou diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysFileController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysFileController.java index 42d68e844..ca8790e55 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysFileController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysFileController.java @@ -26,6 +26,7 @@ import com.pig4cloud.pigx.admin.api.dto.SysFileGroupDTO; import com.pig4cloud.pigx.admin.api.entity.SysFile; import com.pig4cloud.pigx.admin.api.entity.SysFileGroup; import com.pig4cloud.pigx.admin.service.SysFileService; +import com.pig4cloud.pigx.common.api.encrypt.annotation.NoEncrypt; import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.common.log.annotation.SysLog; import com.pig4cloud.pigx.common.security.annotation.Inner; @@ -116,6 +117,7 @@ public class SysFileController { * @return */ @Inner(false) + @NoEncrypt @GetMapping("/oss/file") public void file(String fileName, HttpServletResponse response) { sysFileService.getFile(fileName, response); @@ -127,6 +129,7 @@ public class SysFileController { * @param response 本地文件 */ @SneakyThrows + @NoEncrypt @GetMapping("/local/file/{fileName}") public void localFile(@PathVariable String fileName, HttpServletResponse response) { ClassPathResource resource = new ClassPathResource("file/" + fileName); diff --git a/pigx-visual/pigx-codegen/pom.xml b/pigx-visual/pigx-codegen/pom.xml index 5755b8a24..8a6c2b817 100755 --- a/pigx-visual/pigx-codegen/pom.xml +++ b/pigx-visual/pigx-codegen/pom.xml @@ -150,6 +150,11 @@ com.pig4cloud pigx-common-log + + + com.pig4cloud + pigx-common-encrypt-api + com.pig4cloud diff --git a/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/controller/GeneratorController.java b/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/controller/GeneratorController.java index 043bdf878..773646a36 100755 --- a/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/controller/GeneratorController.java +++ b/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/controller/GeneratorController.java @@ -20,6 +20,7 @@ package com.pig4cloud.pigx.codegen.controller; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import com.pig4cloud.pigx.codegen.service.GeneratorService; +import com.pig4cloud.pigx.common.api.encrypt.annotation.NoEncrypt; import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.common.idempotent.annotation.Idempotent; import lombok.RequiredArgsConstructor; @@ -56,6 +57,7 @@ public class GeneratorController { * @param response 流输出对象 */ @SneakyThrows + @NoEncrypt @GetMapping("/download") @Idempotent(key = "#tableIds", expireTime = 10, info = "正在生成代码,请勿重复操作") public void download(String tableIds, HttpServletResponse response) { diff --git a/pigx-visual/pigx-mp-platform/pom.xml b/pigx-visual/pigx-mp-platform/pom.xml index 79d51de9f..9d1a45985 100755 --- a/pigx-visual/pigx-mp-platform/pom.xml +++ b/pigx-visual/pigx-mp-platform/pom.xml @@ -81,6 +81,11 @@ com.pig4cloud pigx-common-sensitive + + + com.pig4cloud + pigx-common-encrypt-api + com.pig4cloud diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java index e7db71b0a..96cfaa06d 100644 --- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java +++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java @@ -1,6 +1,7 @@ package com.pig4cloud.pigx.mp.controller; import cn.hutool.core.util.StrUtil; +import com.pig4cloud.pigx.common.api.encrypt.annotation.NoEncrypt; import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import com.pig4cloud.pigx.common.data.tenant.TenantBroker; import com.pig4cloud.pigx.common.security.annotation.Inner; @@ -24,7 +25,7 @@ import org.springframework.web.bind.annotation.*; @Inner(value = false) @RestController @AllArgsConstructor -@RequestMapping("/{appId}/portal") +@RequestMapping("/wx-portal/{appId}") public class WxPortalController { /** @@ -74,6 +75,7 @@ public class WxPortalController { * @param nonce 随机数 * @return */ + @NoEncrypt @XssCleanIgnore @PostMapping(produces = "application/xml; charset=UTF-8") public String post(@PathVariable("appId") String appId, @RequestBody String requestBody, diff --git a/pigx-visual/pigx-pay-platform/pom.xml b/pigx-visual/pigx-pay-platform/pom.xml index 47ed68dc9..7a1e3d4e9 100755 --- a/pigx-visual/pigx-pay-platform/pom.xml +++ b/pigx-visual/pigx-pay-platform/pom.xml @@ -78,6 +78,11 @@ com.pig4cloud pigx-common-swagger + + + com.pig4cloud + pigx-common-encrypt-api + com.pig4cloud diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java index c16bd0d29..ffd910ddf 100755 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java @@ -25,6 +25,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ijpay.alipay.AliPayApi; import com.ijpay.core.kit.HttpKit; import com.ijpay.core.kit.WxPayKit; +import com.pig4cloud.pigx.common.api.encrypt.annotation.NoEncrypt; import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel; import com.pig4cloud.pigx.common.log.annotation.SysLog; @@ -146,6 +147,7 @@ public class PayNotifyRecordController { @Inner(false) @SneakyThrows @XssCleanIgnore + @NoEncrypt @PostMapping("/ali/callbak") @Operation(summary = "支付宝渠道异步回调", description = "支付宝渠道异步回调") public void aliCallbak(HttpServletRequest request, HttpServletResponse response) { @@ -161,6 +163,7 @@ public class PayNotifyRecordController { */ @Inner(false) @SneakyThrows + @NoEncrypt @XssCleanIgnore @PostMapping("/wx/callbak") @Operation(summary = "微信渠道支付回调", description = "微信渠道支付回调") @@ -178,6 +181,7 @@ public class PayNotifyRecordController { */ @Inner(false) @SneakyThrows + @NoEncrypt @XssCleanIgnore @PostMapping("/merge/callbak") @Operation(summary = "聚合渠道异步回调", description = "聚合渠道异步回调") diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/RefundNameEnum.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/RefundNameEnum.java index d831508c6..3a703324f 100644 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/RefundNameEnum.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/RefundNameEnum.java @@ -12,25 +12,30 @@ import lombok.Getter; @AllArgsConstructor public enum RefundNameEnum { - /** - * 支付宝wap支付 - */ - ALIPAY("ALIPAY_REFUND", "支付宝退款"), + /** + * 支付宝wap支付 + */ + ALIPAY("ALIPAY_REFUND", "支付宝退款"), - /** - * 微信H5支付 - */ - WEIXIN("WEIXIN_REFUND", "微信退款"); + /** + * 微信H5支付 + */ + WEIXIN("WEIXIN_REFUND", "微信退款"), - /** - * 名称 - */ - @Getter - private String name; + /** + * 合并支付 + */ + MERGE_PAY("MERGE_PAY_REFUND", "合并支付退款"); - /** - * 描述 - */ - private String description; + /** + * 名称 + */ + @Getter + private String name; + + /** + * 描述 + */ + private String description; }