# encrypt-spring-boot-starter **Repository Path**: feizhaiyou/encrypt-spring-boot-starter ## Basic Information - **Project Name**: encrypt-spring-boot-starter - **Description**: 整合SpringBoot可对Web项目的HTTP接口参数进行脱敏与加解密,通过注解的方式直接使用加解密,支持AES、RSA,可自定义脱敏与加解密配置。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: https://feizhaiyou.com - **GVP Project**: No ## Statistics - **Stars**: 9 - **Forks**: 3 - **Created**: 2023-07-27 - **Last Updated**: 2025-07-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![](https://img.shields.io/badge/JDK-1.8+-success.svg) ![](https://img.shields.io/:license-Apache2-orange.svg) # 开源地址 - Gitee:[https://gitee.com/feizhaiyou/encrypt-spring-boot-starter/tree/master/](https://gitee.com/feizhaiyou/encrypt-spring-boot-starter/tree/master/) - 分支说明: - master:发布版【使用请拉取该分支】 - dev:开发中 - 实践DEMO:https://gitee.com/feizhaiyou/encrypt-test # 使用说明 ## 介绍 对SpringWeb项目中SpringMVC注解(`@RequestMapping`、`@GetMapping`、`@PostMapping`、`@PutMapping`、`@DeleteMapping`)的接口参数进行脱敏与加解密,仅限于Http请求中字符串类型的参数数据生效,可进行充分扩展,可自进行定义脱敏、加解密等。 ## 版本说明 - 1.0.0版本 内置加密方式:AES、RSA(默认加密模式) 高级用法:支持 - 1.0.1版本【latest-version】 内置加密方式:支持AES、RSA加密,新增国密SM2、SM4加密方式 增加内置加密器密钥生成:[内置加密器密钥生成](# 内置加密器密钥生成) 高级用法:支持,文档更新[自定义加密器](# 自定义加密器)配置及使用方式 日志输出:DEBUG级别支持详细日志方便调试 ## 导入依赖 - Maven: > 依赖已发布至Maven中央仓库,可直接引入依赖。 > > https://mvnrepository.com/artifact/com.feizhaiyou.encrypt/encrypt-spring-boot-starter ```xml com.feizhaiyou.encrypt encrypt-spring-boot-starter ${latest-version} ``` - Gradle > 请自行替换版本号 ``` // https://mvnrepository.com/artifact/com.feizhaiyou.encrypt/encrypt-spring-boot-starter implementation group: 'com.feizhaiyou.encrypt', name: 'encrypt-spring-boot-starter', version: '1.0.0' ``` - 本地: > `git`拉取代码到本地,执行`mvn install`(选择`profile`为`local`,例如:`mvn clean install -Plocal`)打包下载到本地Maven仓库,项目maven pom引入 ```xml com.feizhaiyou.encrypt encrypt-spring-boot-starter ${latest-version} ``` ### maven依赖说明 maven中央仓库不支持自行提交jar包,因此我们只能将jar包发布到它指定的第三方maven仓库(sonatype),这会导致maven中央和其他镜像仓库(阿里云等)有同步延迟。解决方案: 1. 使用源码直接安装到本地maven仓库 2. 修改远程maven仓库地址 ```xml central sonatype-central https://s01.oss.sonatype.org/content/groups/public/ central ``` ## 项目配置 对称加密:AES 密钥请自行生成【[内置加密器密钥生成](# 内置加密器密钥生成)】 ```yaml fzy: security: #是否启动脱敏与加密,默认true enable: true #加密后的编码模式:base64、hex,默认base64 mode: base64 #参数字段递归深度,默认5 max-deep: 5 #加密方式:AES、RSA,默认AES(1.0.1新增内置SM2和SM4加密方式) type: AES #对称加密密钥 密钥请自行生成 secret: +6cuvzvyrFZpRG9pf3r7eQ== #脱敏与加解密实体类所在包 支持包前缀和正则匹配 class-package: - com.feizhaiyou.test.entity #字符集 charset: UTF-8 ``` 非对称加密:RSA privateKey与publicKey请自行生成【[内置加密器密钥生成](# 内置加密器密钥生成)】 ```yaml fzy: security: enable: true mode: hex max-deep: 5 type: RSA class-package: - com.feizhaiyou.test.entity charset: UTF-8 public-key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQwb536Gb2eZ60H/4VQRJUpod0M04yCR6IaEdgAbBACWvc5E2s7gCipO9IQB5tiU08JSQ2Mmfg88uGffK6z5YcKJ/CNWByiNHL3B2GzsgMMBh2a5Dba+KqA3ZFkeXhkw8htej18mM4Xw1KGytAni7sypzjynC+4/m7FcewB6BBxQIDAQAB private-key: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJDBvnfoZvZ5nrQf/hVBElSmh3QzTjIJHohoR2ABsEAJa9zkTazuAKKk70hAHm2JTTwlJDYyZ+Dzy4Z98rrPlhwon8I1YHKI0cvcHYbOyAwwGHZrkNtr4qoDdkWR5eGTDyG16PXyYzhfDUobK0CeLuzKnOPKcL7j+bsVx7AHoEHFAgMBAAECgYBC6av3lW/ywuk/bgJvJLMqegfnCMg+jMSWXU2Q7XbhQvmfE9Fr/GBCzmblSO5Hx83x3WFNxCMMcuVDd/i5rbc+/fKoYyEhuOI91bHRxWR2M1VkNAZpUMeccGM/g15/p0P4pNEFYEaXkUZ170Je8aaECmr8v24ukvGlKFE38RuWgQJBANZCIkBxtY3H3CnT4LXX8NaJlWh7SpSZJsazwblDbubCMBJ+3qSaKxCE9v3d8F9QVPvZKgwd7uWIXHtcDygigVUCQQCs9U8NpV0VgZKbJzEuxaelpmi7eCe02hc5C1NVxQ14vRmV8na//GYOI6s0fNZjkPPGdRvmsTRpDYAeR3U/qX6xAkA+aed2ZGlh0s2Uta7o6e2zYULPu9Ke9Poxud197WHaAMlmKeULiAlxd3pHu6Yw7cLD1qAEBZg47v8ZxFh59Ys9AkEAjk4fxxiB6An+OA4dF2ClOVQb4/NOqCyw4syAupcxKGBeRtOCBSCET6nlWYBFXRKMoIMGe97dQnpLKZ6dx82LYQJBAJADjI2XGtg5HlgIzOLMMsTJ4+3OqCiJLoNAkmozckSQveyuh0Jh0Vvs1nTdfR1DMbsrIR2Me/ugPXzVvtEpU80= ``` ### 内置加密器密钥生成 - 1.0.1新增 ```java public static void main(String[] args) { // 调用对应的加密器的generateKey()方法即可 Map keyMap = SM2Processor.generateKey(); System.out.println("SM2 publicKey: " + keyMap.get("PUB")); System.out.println("SM2 privateKey: " + keyMap.get("PRV")); // 支持指定密钥字符串的编码模式:SecurityMode.BASE64, SecurityMode.HEX String key = SM4Processor.generateKey(SecurityMode.HEX); System.out.println("SM4 secret: " + key); } ``` 说明: > 调用内置加密器的`generateKey()`静态方法即可,对称加密直接返回密钥`String`,非对称加密返回`Map`,`map.get("PUB")`为生成的公钥,`map.get("PRV")`为生成的私钥。 > > 内置加密器: > > AES:`com.feizhaiyou.encrypt.codec.AESProcessor` > > RSA:`com.feizhaiyou.encrypt.codec.RSAProcessor` > > SM2:`com.feizhaiyou.encrypt.codec.SM2Processor` > > SM4:`com.feizhaiyou.encrypt.codec.SM4Processor` ## 响应数据脱敏`@Sensitive` 在实体类属性或者接口方法(针对直接响应字符串的情况)上使用`@Sensitive`注解即可。 注解属性说明: | 参数名 | 类型 | 默认值 | 说明 | | -------- | ------- | -------------------------------------------------------- | -------------------------- | | required | boolean | true | 是否开启字段加密,默认开启 | | type | String | `com.feizhaiyou.encrypt.constants.SensitiveType.DEFUALT` | 脱敏参数类型 | 注意:`@Sensitive`注解必须用在字符串类型的参数字段或接口返回类型为字符串的接口方法上。 ### 实体类字段使用`@Sensitive`注解 ```java package com.feizhaiyou.test.entity; import com.feizhaiyou.encrypt.annotation.Sensitive; import com.feizhaiyou.encrypt.constants.SensitiveType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; /** * @author ls * @since 2023-07-28 */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class User { private String id; @Sensitive(type = SensitiveType.CHINESE_NAME) private String name; @Sensitive(type = SensitiveType.ID_CARD) private String idCard; @Sensitive(type = SensitiveType.EMAIL) private String email; @Sensitive(type = SensitiveType.MOBILE_PHONE) private String phone; private List
addressList; } ``` ```java package com.feizhaiyou.test.entity; import com.feizhaiyou.encrypt.annotation.Sensitive; import com.feizhaiyou.encrypt.constants.SensitiveType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @author ls * @since 2023-07-28 */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Address { private String id; @Sensitive(type = SensitiveType.ADDRESS) private String address; private String areaCode; } ``` Controller ```java package com.feizhaiyou.test.controller; import com.feizhaiyou.encrypt.annotation.Sensitive; import com.feizhaiyou.test.entity.Address; import com.feizhaiyou.test.entity.Result; import com.feizhaiyou.test.entity.User; import org.springframework.web.bind.annotation.*; import java.util.Collections; import java.util.UUID; /** * @author ls * @since 2023-07-28 */ @RestController @RequestMapping("/test") public class TestController { @GetMapping("/get/{id}") public Result get(@PathVariable("id") String id) { User user = User.builder() .id(id) .idCard("110222199703036666") .email("243607654@qq.com") .name("热巴") .phone("13939393939") .addressList(Arrays.asList(Address.builder() .address("北京市东城区长安街") .areaCode("100000") .id(UUID.randomUUID().toString()) .build())).build(); return Result.OK(user); } } ``` PostMan调用测试: ![](https://file.feizhaiyou.com/csdn/7935f49c875249c89582886af84baa45.png) ### 接口方法上使用`@Sensitive`注解 Controller ```java package com.feizhaiyou.test.controller; import com.feizhaiyou.encrypt.annotation.Sensitive; import com.feizhaiyou.test.entity.Address; import com.feizhaiyou.test.entity.Result; import com.feizhaiyou.test.entity.User; import org.springframework.web.bind.annotation.*; import java.util.Collections; import java.util.UUID; /** * @author ls * @since 2023-07-21 */ @RestController @RequestMapping("/test") public class TestController { @GetMapping("/getAddress") @Sensitive public String getAddress() { return "北京市东城区长安街"; } } ``` PostMan调用测试: ![](https://file.feizhaiyou.com/csdn/8dcb190431f845b6bf95e1a2afca8772.png) ## 响应请求参数加解密`@Security` 在实体类属性或者接口方法(针对直接响应字符串的情况)上使用`@Security`注解即可。 注解属性说明: | 参数名 | 类型 | 默认值 | 说明 | | ------- | ------- | ------ | ------------------------ | | encrypt | boolean | true | 是否对响应加密,默认开启 | | decrypt | boolean | true | 是否对请求解密,默认开启 | 注意:`@Security`注解必须用在字符串类型的参数(实体类属性或方法参数)或接口返回类型为字符串的接口方法上。 ### 实体类字段使用`@Security`注解 ```java package com.feizhaiyou.test.entity; import com.feizhaiyou.encrypt.annotation.Security; import com.feizhaiyou.encrypt.annotation.Sensitive; import com.feizhaiyou.encrypt.constants.SensitiveType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Data @Builder @NoArgsConstructor @AllArgsConstructor public class User { private String id; // name 即加密又解密 @Security private String name; // idCard 不进行解密只加密 @Security(decrypt = false) private String idCard; // email 不进行加密只解密 @Security(encrypt = false) private String email; private String phone; private List
addressList; } ``` ```java package com.feizhaiyou.test.entity; import com.feizhaiyou.encrypt.annotation.Security; import com.feizhaiyou.encrypt.annotation.Sensitive; import com.feizhaiyou.encrypt.constants.SensitiveType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @author ls * @since 2023-07-28 */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Address { private String id; @Security private String address; private String areaCode; } ``` Controller ```java @PostMapping("/post/{id}") public Result get(@PathVariable("id") String id, @RequestBody User user) { System.out.println("id = " + id + ", user = " + user); return Result.OK(user); } ``` PostMan调用测试: ![](https://file.feizhaiyou.com/csdn/4baf13cb8a1744579b2c13d4a2382453.png) 控制台输出: ![](https://file.feizhaiyou.com/csdn/fd2c0441a05a47f780e4d2822489ef5c.png) ### 接口方法中使用`@Security`注解 Controller ```java @GetMapping("/getEmail") @Security public String getEmail(@Security String name) { System.out.println("name = " + name); return "243607654@qq.com"; } ``` PostMan调用测试: ![](https://file.feizhaiyou.com/csdn/7a415d0fc3e14d5b8c44c7c85900069f.png) 控制台输出: ![](https://file.feizhaiyou.com/csdn/d44a97d6ca74411193c587e0d3f898ef.png) 说明: > 用在方法上,可以对接口响应的字符串进行加密 > > 用在参数中,可以对接口请求参数的字符串进行解密 # 高级用法 ## 自定义加密器 ### 1.实现SecurityProcessor接口 实现`com.feizhaiyou.encrypt.codec.SecurityProcessor`接口,实现`byte[] encrypt(byte[] data)`加密方法和`byte[] decrypt(String text)`解密方法,例如: ```java package com.feizhaiyou.test.codec; import cn.hutool.core.codec.Base64Encoder; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.Mode; import cn.hutool.crypto.Padding; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.symmetric.DES; import com.feizhaiyou.encrypt.codec.SecurityProcessor; import com.feizhaiyou.encrypt.constants.SecurityMode; import lombok.Data; import lombok.extern.slf4j.Slf4j; /** * 自定义加密器实现 * 加密模式:DES/CTS/PKCS5Padding * * @author ls */ @Data @Slf4j public class MyProcessor implements SecurityProcessor { private String secret; private String salt; private DES des; /** * DES/CTS/PKCS5Padding * * @param secret 密钥 * @param salt 盐(偏移量)8字节 */ public MyProcessor(String secret, String salt) { this.secret = secret; this.salt = salt; this.des = new DES(Mode.CTS, Padding.PKCS5Padding, SecureUtil.decode(secret), salt.getBytes()); } @Override public byte[] decrypt(String text) { return des.decrypt(text); } @Override public byte[] encrypt(byte[] data) { return des.encrypt(data); } /** * 以base64编码生成 DES/CTS/PKCS5Padding 秘钥 * * @return */ public static String generateKey() { return generateKey(SecurityMode.BASE64); } /** * 生成 DES/CTS/PKCS5Padding 秘钥 * * @param type {@link SecurityMode} 编码模式 * @return */ public static String generateKey(SecurityMode type) { byte[] keyBytes = SecureUtil.generateKey("DES/CTS/PKCS5Padding").getEncoded(); switch (type) { case HEX: return HexUtil.encodeHexStr(keyBytes); case BASE64: default: return Base64Encoder.encode(keyBytes); } } public static void main(String[] args) { String secret = generateKey(); System.out.println(secret); MyProcessor processor = new MyProcessor("KRxwmyr37N8=", "12345678"); byte[] encrypt = processor.encrypt("北京市东城区长安街".getBytes()); String encode1 = Base64Encoder.encode(encrypt); System.out.println(encode1); byte[] decrypt = processor.decrypt(encode1); System.out.println(StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8)); } } ``` ### 2.将自定义加密器添加到Spring容器 ```java package com.feizhaiyou.test; import com.feizhaiyou.encrypt.codec.SecurityProcessor; import com.feizhaiyou.test.codec.MyProcessor; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; /** * TestApplication * * @author Jason */ @SpringBootApplication @EnableAspectJAutoProxy public class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class); System.out.println("启动成功"); } @Bean @ConditionalOnMissingBean // 定义fzy.security.type属性值为MY时加载此加密器 @ConditionalOnProperty(prefix = "fzy.security", name = "type", havingValue = "MY") public SecurityProcessor myProcessor() { // 密钥和加盐可从配置文件中读取 return new MyProcessor("KRxwmyr37N8=", "12345678"); } } ``` ### 3.配置文件配置 ```yaml server: port: 1010 logging: level: # 日志输出 com.feizhaiyou.encrypt: debug org.springframework: warn fzy: security: enable: true mode: base64 max-deep: 5 # 配置为自定义的加密器 type: MY class-package: - com.feizhaiyou.test.entity charset: UTF-8 ``` ### 4.启动 DEBUG级日志输出加载的自定义加密器 ![](https://file.feizhaiyou.com/csdn/direct/da734545a7d84ac992df93ba5ef4c61b.png) # 开源项目 - [Hutool](https://hutool.cn/)是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。