中文 | English |
futu-api-encrypt is an API encryption/decryption starter based on spring-boot and spring-cloud-gateway. Through simple spring-boot configuration, it can implement interface parameter validation and encryption/decryption in various business scenarios. It includes features such as timestamp validation, signature verification, symmetric encryption , asymmetric encryption, and can filter interface addresses based on whitelist and blacklist. It also supports Tolerant Mode for flexible handling of both encrypted and non-encrypted requests.
Based on spring-cloud-gateway (similar for spring-boot)
<dependency>
<groupId>cn.futuai.open</groupId>
<artifactId>futu-api-encrypt-spring-cloud-gateway-starter</artifactId>
<version>1.3.3</version>
</dependency>
spring:
cloud:
gateway:
api-encrypt:
# Global switch
enabled: true
# Encryption symmetric key http header key
encrypt-aes-key-header-key: "ek"
# Timestamp http header key
timestamp-header-key: "ts"
# Signature value http header key
sign-header-key: "sign"
# Encrypted query parameter key
encrypt-param-key: "ciphertext"
# RSA asymmetric encryption private key
rsa-private-key: "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAI6VKvsus/Z0R3zvqre3gzClHJdsCVeKq89hZFFWbg5l3FNbiGZEEiuD1LL+USi5GCxeRK+xEOFTj7I/waRVb3x7V3J1N0q4nNWoZvRey0MTVaBkoHeB5tzn2ZOCBQRJnijXcO58ChcLXOTQId+zDiCBCom/A62gtH8isH4PYoZXAgMBAAECgYBpetrwNa223nDgcWFHRkCMZSmQr8D9fT37Th5rudfzWNG07RssJKGYhY9913xs9vl2IUsI+qH1P98nS9lSXE37mfOKFhfGZIUjAhMb7/w8hhuHpBXopVpUJZW0B46gfPOsrmvq+xiwlI02UYJ1ZOrfdfbvss/Gwtgrk4pMigL1OQJBANRm4mOUMwF+xUxeOLa2Aafke/iwdcxoV1k1gXmTH0B8wf08zDR7heW737YBEvsjyfEpjo7Y0kGSE5zmTWNnuKUCQQCr2XuZeJLqq6etq7IhboPAx8E2xgfOY/hgKPr9IvM8gYee628YhyOynIhOVFGxaf7dMH9eZ1P6jAbvsgm+mFZLAkEAyY0btJyTzg5q0G30aUTKy3OgRDvGfIJiqM+CHkiCdmIsfs5rhD3WsEqYHZBlX5T1cvgZQ+nxkrE4FUHhG7v31QJAYJZ9TNYjJTjTpt5A4V9/OAROCZ4mVw+DU3DVGR/ivJhFBMJpD80s+D/YsMXdoKzlraaLgCDtZ336jBByP6jZnwJBAIGUnbs7eRLcXzlbORdKC/EfkDYS2rrXLFvQhehT7Y8dKHLZfJElnrHB33Qd8R8WP0PsPU6D7EWNU2zVNK1EDxY="
# Tolerant mode configuration
tolerant-urls:
- /api/public/** # Allow public APIs to support both encrypted and non-encrypted access
- /api/legacy/** # Compatible with legacy versions
log-level:
"default": warn
"[/api/user/code]": info
"[/api/user/code2]": debug
"[/api/user/code3]": warn
"[/api/user/code4]": error
"[/api/user/export]": trace
# Detection mode
check-model:
# Mode
model: black_list
# Blacklist URLs
black-list:
- /api/user/code
- /api/user/code2
- /api/user/code3
- /api/user/code4
- /api/user/export
timestamp:
# Timestamp validation switch
enabled: true
# Timestamp valid seconds
timestamp-valid-second: 31536000 # 1 year
sign:
# Signature validation switch
enabled: true
# Request decryption configuration
request-decrypt:
# Enable switch
enabled: true
# Detection mode
check-model:
# Whitelist mode
model: white_list
# Whitelist URLs
white-list:
- /api/user/code2
- /api/user/code4
# Response encryption configuration
response-encrypt:
# Enable switch
enabled: true
# Detection mode
check-model:
# Blacklist mode
model: black_list
# Blacklist URLs
black-list:
- /api/user/code
- /api/user/code4
- /api/user/export
@Configuration
public class ApiEncryptConfiguration {
public ApiEncryptConfiguration() {
// Gateway callback manager
GatewayApiExceptionCallbackManager.setApiExceptionHandler(new GatewayApiExceptionRequestHandler() {
/**
* Called when gateway API validation fails
* @param serverWebExchange serverWebExchange
* @param throwable exception
* @return mono
*/
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange,
Throwable throwable) {
Response<Void> error = Response.create(ResponseTypeEnum.PARAM_VALID_ERROR);
String errJson = JSONUtil.toJsonStr(error);
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(errJson), String.class);
}
});
}
}
Tolerant Mode is a special feature that allows specific API endpoints to support both encrypted and non-encrypted requests simultaneously. This is particularly useful in the following scenarios:
Usage:
tolerant-urls
in the configuration file/api/public/**
@Slf4j
@RestController
public class UserController {
@PostMapping("{path}")
public Map<String, Object> code(@PathVariable("path") String path, @RequestParam String test1,
@RequestParam String test2,
@RequestParam String test3,
@RequestBody String body) {
Map<String, Object> map = new HashMap<>();
map.put("path", path);
map.put("test1", test1);
map.put("test2", test2);
map.put("test3", test3);
map.put("body", body);
log.info(String.valueOf(map));
return map;
}
@SneakyThrows
@GetMapping("export")
public void export(HttpServletResponse response) {
HttpHeaders headers = new HttpHeaders();
String name = "Test File";
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", UriUtils.encode(name, StandardCharsets.UTF_8) + ".xlsx");
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
response.setHeader(entry.getKey(), String.join(";", entry.getValue()));
}
IOUtils.copy(new FileInputStream("D:\\project\\personal\\futu-api-encrypt\\example\\doc\\测试.xlsx"),
response.getOutputStream());
}
}