+ * 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 top.charles7c.continew.starter.security.crypto.annotation; + +import top.charles7c.continew.starter.security.crypto.encryptor.IEncryptor; +import top.charles7c.continew.starter.security.crypto.enums.Algorithm; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 字段加/解密注解 + * + * @author Charles7c + * @since 1.4.0 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface FieldEncrypt { + + /** + * 加密/解密算法 + */ + Algorithm value() default Algorithm.AES; + + /** + * 加密/解密处理器 + *
+ * 优先级高于加密/解密算法 + *
+ */ + Class extends IEncryptor> encryptor() default IEncryptor.class; + + /** + * 对称加密算法密钥 + */ + String password() default ""; +} \ No newline at end of file diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/autoconfigure/CryptoAutoConfiguration.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/autoconfigure/CryptoAutoConfiguration.java new file mode 100644 index 00000000..a34e9ad3 --- /dev/null +++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/autoconfigure/CryptoAutoConfiguration.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *+ * 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 top.charles7c.continew.starter.security.crypto.autoconfigure; + +import jakarta.annotation.PostConstruct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import top.charles7c.continew.starter.core.constant.PropertiesConstants; +import top.charles7c.continew.starter.security.crypto.core.MyBatisDecryptInterceptor; +import top.charles7c.continew.starter.security.crypto.core.MyBatisEncryptInterceptor; + +/** + * 加/解密自动配置 + * + * @author Charles7c + * @since 1.4.0 + */ +@AutoConfiguration +@EnableConfigurationProperties(CryptoProperties.class) +@ConditionalOnProperty(prefix = PropertiesConstants.CRYPTO, name = PropertiesConstants.ENABLED, havingValue = "true", matchIfMissing = true) +public class CryptoAutoConfiguration { + + private static final Logger log = LoggerFactory.getLogger(CryptoAutoConfiguration.class); + private final CryptoProperties properties; + + public CryptoAutoConfiguration(CryptoProperties properties) { + this.properties = properties; + } + + /** + * MyBatis 加密拦截器配置 + */ + @Bean + @ConditionalOnMissingBean(MyBatisEncryptInterceptor.class) + public MyBatisEncryptInterceptor myBatisEncryptInterceptor() { + return new MyBatisEncryptInterceptor(properties); + } + + /** + * MyBatis 解密拦截器配置 + */ + @Bean + @ConditionalOnMissingBean(MyBatisDecryptInterceptor.class) + public MyBatisDecryptInterceptor myBatisDecryptInterceptor() { + return new MyBatisDecryptInterceptor(properties); + } + + @PostConstruct + public void postConstruct() { + log.debug("[ContiNew Starter] - Auto Configuration 'Security-Crypto' completed initialization."); + } +} diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/autoconfigure/CryptoProperties.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/autoconfigure/CryptoProperties.java new file mode 100644 index 00000000..a4df2104 --- /dev/null +++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/autoconfigure/CryptoProperties.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *
+ * 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 top.charles7c.continew.starter.security.crypto.autoconfigure; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import top.charles7c.continew.starter.core.constant.PropertiesConstants; + +/** + * 加/解密配置属性 + * + * @author Charles7c + * @since 1.4.0 + */ +@ConfigurationProperties(PropertiesConstants.CRYPTO) +public class CryptoProperties { + + /** + * 是否启用加/解密配置 + */ + private boolean enabled = true; + + /** + * 对称加密算法密钥 + */ + private String password; + + /** + * 非对称加密算法公钥 + */ + private String publicKey; + + /** + * 非对称加密算法私钥 + */ + private String privateKey; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getPublicKey() { + return publicKey; + } + + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + public String getPrivateKey() { + return privateKey; + } + + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + } +} \ No newline at end of file diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/core/AbstractMyBatisInterceptor.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/core/AbstractMyBatisInterceptor.java new file mode 100644 index 00000000..378f0ae5 --- /dev/null +++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/core/AbstractMyBatisInterceptor.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *
+ * 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 top.charles7c.continew.starter.security.crypto.core;
+
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import org.apache.ibatis.plugin.*;
+import top.charles7c.continew.starter.security.crypto.annotation.FieldEncrypt;
+import top.charles7c.continew.starter.security.crypto.encryptor.IEncryptor;
+import top.charles7c.continew.starter.security.crypto.enums.Algorithm;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 字段解密拦截器
+ *
+ * @author Charles7c
+ * @since 1.4.0
+ */
+public abstract class AbstractMyBatisInterceptor implements Interceptor {
+
+ /**
+ * 获取所有字符串类型、需要加/解密的、有值字段
+ *
+ * @param obj 对象
+ * @return 字段列表
+ */
+ public List
+ * 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 top.charles7c.continew.starter.security.crypto.core;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReflectUtil;
+import org.apache.ibatis.executor.resultset.ResultSetHandler;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.type.SimpleTypeRegistry;
+import top.charles7c.continew.starter.security.crypto.annotation.FieldEncrypt;
+import top.charles7c.continew.starter.security.crypto.autoconfigure.CryptoProperties;
+import top.charles7c.continew.starter.security.crypto.encryptor.IEncryptor;
+
+import java.lang.reflect.Field;
+import java.sql.Statement;
+import java.util.List;
+
+/**
+ * 字段解密拦截器
+ *
+ * @author Charles7c
+ * @since 1.4.0
+ */
+@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
+public class MyBatisDecryptInterceptor extends AbstractMyBatisInterceptor {
+
+ private CryptoProperties properties;
+
+ public MyBatisDecryptInterceptor(CryptoProperties properties) {
+ this.properties = properties;
+ }
+
+ public MyBatisDecryptInterceptor() {
+ }
+
+ @Override
+ public Object intercept(Invocation invocation) throws Throwable {
+ Object obj = invocation.proceed();
+ if (null == obj || !(invocation.getTarget() instanceof ResultSetHandler)) {
+ return obj;
+ }
+ List> resultList = (List>)obj;
+ for (Object result : resultList) {
+ // String、Integer、Long 等简单类型对象无需处理
+ if (SimpleTypeRegistry.isSimpleType(result.getClass())) {
+ continue;
+ }
+ // 获取所有字符串类型、需要解密的、有值字段
+ List
+ * 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 top.charles7c.continew.starter.security.crypto.core;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReflectUtil;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.plugin.*;
+import top.charles7c.continew.starter.security.crypto.annotation.FieldEncrypt;
+import top.charles7c.continew.starter.security.crypto.autoconfigure.CryptoProperties;
+import top.charles7c.continew.starter.security.crypto.encryptor.IEncryptor;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ * 字段加密拦截器
+ *
+ * @author Charles7c
+ * @since 1.4.0
+ */
+@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}),})
+public class MyBatisEncryptInterceptor extends AbstractMyBatisInterceptor {
+
+ private CryptoProperties properties;
+
+ public MyBatisEncryptInterceptor(CryptoProperties properties) {
+ this.properties = properties;
+ }
+
+ public MyBatisEncryptInterceptor() {
+ }
+
+ @Override
+ public Object intercept(Invocation invocation) throws Throwable {
+ Object[] args = invocation.getArgs();
+ MappedStatement mappedStatement = (MappedStatement)args[0];
+ SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
+ if (!(SqlCommandType.UPDATE == sqlCommandType || SqlCommandType.INSERT == sqlCommandType)) {
+ return invocation.proceed();
+ }
+ Object obj = args[1];
+ // 兼容 MyBatis Plus 封装的 update 相关方法,updateById、update
+ if (obj instanceof Map map) {
+ Object entity = map.get(Constants.ENTITY);
+ this.doEncrypt(this.getEncryptFields(entity), entity);
+ } else {
+ this.doEncrypt(this.getEncryptFields(obj), obj);
+ }
+ return invocation.proceed();
+ }
+
+ /**
+ * 处理加密
+ *
+ * @param fieldList 加密字段列表
+ * @param entity 实体
+ * @throws Exception /
+ */
+ private void doEncrypt(List
+ * 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 top.charles7c.continew.starter.security.crypto.encryptor;
+
+import cn.hutool.crypto.SecureUtil;
+import cn.hutool.crypto.symmetric.AES;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * AES(Advanced Encryption Standard) 加/解密处理器
+ *
+ * 美国国家标准与技术研究院(NIST)采纳的对称加密算法标准,提供128位、192位和256位三种密钥长度,以高效和安全性著称。
+ *
+ * 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 top.charles7c.continew.starter.security.crypto.encryptor;
+
+import cn.hutool.core.codec.Base64;
+
+/**
+ * Base64 加/解密处理器
+ *
+ * 一种用于编码二进制数据到文本格式的算法,常用于邮件附件、网页传输等场合,但它不是一种加密算法,只提供数据的编码和解码,不保证数据的安全性。
+ *
+ * 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 top.charles7c.continew.starter.security.crypto.encryptor;
+
+/**
+ * 加/解密接口
+ *
+ * @author Charles7c
+ * @since 1.4.0
+ */
+public interface IEncryptor {
+
+ /**
+ * 加密
+ *
+ * @param plaintext 明文
+ * @param password 对称加密算法密钥
+ * @param publicKey 非对称加密算法公钥
+ * @return 加密后的文本
+ * @throws Exception /
+ */
+ String encrypt(String plaintext, String password, String publicKey) throws Exception;
+
+ /**
+ * 解密
+ *
+ * @param ciphertext 密文
+ * @param password 对称加密算法密钥
+ * @param privateKey 非对称加密算法私钥
+ * @return 解密后的文本
+ * @throws Exception /
+ */
+ String decrypt(String ciphertext, String password, String privateKey) throws Exception;
+}
diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/encryptor/RsaEncryptor.java b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/encryptor/RsaEncryptor.java
new file mode 100644
index 00000000..e49c4214
--- /dev/null
+++ b/continew-starter-security/continew-starter-security-crypto/src/main/java/top/charles7c/continew/starter/security/crypto/encryptor/RsaEncryptor.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * 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 top.charles7c.continew.starter.security.crypto.encryptor;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.crypto.SecureUtil;
+import cn.hutool.crypto.asymmetric.KeyType;
+
+/**
+ * RSA 加/解密处理器
+ *
+ * 非对称加密算法,由罗纳德·李维斯特(Ron Rivest)、阿迪·沙米尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)于1977年提出,安全性基于大数因子分解问题的困难性。
+ *
+ * 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 top.charles7c.continew.starter.security.crypto.enums;
+
+import top.charles7c.continew.starter.security.crypto.encryptor.AesEncryptor;
+import top.charles7c.continew.starter.security.crypto.encryptor.Base64Encryptor;
+import top.charles7c.continew.starter.security.crypto.encryptor.IEncryptor;
+import top.charles7c.continew.starter.security.crypto.encryptor.RsaEncryptor;
+
+/**
+ * 加密/解密算法枚举
+ *
+ * @author Charles7c
+ * @since 1.4.0
+ */
+public enum Algorithm {
+
+ /**
+ * AES
+ */
+ AES(AesEncryptor.class),
+
+ /**
+ * RSA
+ */
+ RSA(RsaEncryptor.class),
+
+ /**
+ * Base64
+ */
+ BASE64(Base64Encryptor.class),;
+
+ /**
+ * 加密/解密处理器
+ */
+ private final Class extends IEncryptor> encryptor;
+
+ Algorithm(Class extends IEncryptor> encryptor) {
+ this.encryptor = encryptor;
+ }
+
+ public Class extends IEncryptor> getEncryptor() {
+ return encryptor;
+ }
+}
diff --git a/continew-starter-security/continew-starter-security-crypto/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/continew-starter-security/continew-starter-security-crypto/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..c4a825ee
--- /dev/null
+++ b/continew-starter-security/continew-starter-security-crypto/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+top.charles7c.continew.starter.security.crypto.autoconfigure.CryptoAutoConfiguration
\ No newline at end of file
diff --git a/continew-starter-security/pom.xml b/continew-starter-security/pom.xml
index 892a1bf9..666fad34 100644
--- a/continew-starter-security/pom.xml
+++ b/continew-starter-security/pom.xml
@@ -16,6 +16,7 @@