Mã hoá dữ liệu
Lớp trừu tượng mã hoá (EncryptService) kèm hai cơ chế tích hợp sẵn: giải mã body request với @DecryptRequestBody và mã hoá/giải mã thuộc tính JSON với @JsonPropertyEncrypt.
Khi nào sử dụng
- API nhận dữ liệu nhạy cảm (mật khẩu, thông tin cá nhân) cần giải mã ở tầng request body.
- Cần lưu cấu hình chứa bí mật (mật khẩu SMTP, API key...) đã mã hoá trong DB nhưng vẫn đọc/ghi qua object Java bình thường.
- Cần một interface thống nhất để mã hoá/giải mã và có thể thay implementation theo ứng dụng.
- Cần giải mã body thủ công trong filter/listener ngoài luồng controller.
Cài đặt
Thêm dependency vào pom.xml, không cần khai báo version vì BOM đã quản lý:
<dependency>
<groupId>vn.govex.cloud</groupId>
<artifactId>govex-cloud-crypto</artifactId>
</dependency>
Hướng dẫn khai báo parent/BOM và Maven repository xem tại Cài đặt.
Cấu hình
Cần tự khai báo các bean/hạng mục sau:
| Bean / hạng mục | Vai trò |
|---|---|
EncryptService | Interface mã hoá/giải mã; implementation mặc định nằm ở govex-cloud-config (AES, khoá từ setting security.aes_secret) |
DecryptRequestBodyAdvice | Bean bắt buộc để @DecryptRequestBody hoạt động; govex-cloud-security đăng ký sẵn, nếu không dùng govex-cloud-security thì khai báo thủ công |
EncryptionModule | Jackson module xử lý @JsonPropertyEncrypt; tạo qua EncryptionModule.serializerEncrypt(), deserializerDecrypt()... |
Session attribute IAM_ENCRYPT_SECRET | Khoá AES dùng một lần cho mỗi request, do luồng đăng nhập thiết lập và bị xoá sau khi giải mã |
Sử dụng
Giải mã request body
@PostMapping("/change-password")
public ResultMessage<Boolean> changePassword(
@DecryptRequestBody @RequestBody ChangePasswordRequest request) {
return accountService.changePassword(request);
}
Client gửi body theo cấu trúc mà dependency yêu cầu:
{
"encrypt": "<chuỗi-base64-đã-mã-hoá-AES>"
}
Nếu không dùng govex-cloud-security, đăng ký bean advice:
@Bean
DecryptRequestBodyAdvice decryptRequestBodyAdvice() {
return new DecryptRequestBodyAdvice();
}
Dùng EncryptService trong code
@Service
@RequiredArgsConstructor
public class SecretStore {
private final EncryptService encryptService;
public String encrypt(String raw) {
return encryptService.encrypt(raw);
}
public String decrypt(String encrypted) {
return encryptService.decrypt(encrypted);
}
}
Mã hoá thuộc tính JSON
Đánh dấu field cần mã hoá:
public class MailProviderConfig {
@JsonPropertyEncrypt
private String password;
}
Khi serialize/deserialize, các field được đánh dấu được xử lý tự động:
// Serialize: password được mã hoá trước khi ghi xuống DB
ObjectMapper encryptMapper = EncryptionModule.serializerEncrypt();
String stored = encryptMapper.writeValueAsString(config);
// Deserialize: password được giải mã khi đọc lên
ObjectMapper decryptMapper = EncryptionModule.deserializerDecrypt();
MailProviderConfig loaded = decryptMapper.readValue(stored, MailProviderConfig.class);
Giải mã body thủ công
try (InputStream is = request.getInputStream()) {
String body = DecryptRequestBodyAdvice.decryptBody(is);
// xử lý tiếp với body đã giải mã
}
Lưu ý
- Cần tự khai báo
EncryptServicevàDecryptRequestBodyAdvicethì tính năng mới hoạt động đầy đủ. @DecryptRequestBodygắn trên tham số kèm@RequestBody; luồng đăng nhập phải thiết lập session attributeIAM_ENCRYPT_SECRETtrước khi gọi API.- Khoá giải mã bị xoá khỏi session sau mỗi lần dùng — client/phiên cần lấy khoá mới cho lần gửi kế tiếp theo luồng của hệ thống.
- Nếu chưa có bean
EncryptService, các serializer/deserializer củaEncryptionModuletrả về giá trị nguyên bản thay vì báo lỗi — dễ gây nhầm lẫn khi kiểm thử. @JsonPropertyEncrypt(packagevn.govex.cloud.api.jackson) hỗ trợ chọn chiều xử lý quaserializer/deserializervớiJsonEncryptType(ENCRYPT,DECRYPT,NONE); mặc định serializerENCRYPT, deserializerDECRYPT.govex-cloud-securityđã đăng ký sẵnDecryptRequestBodyAdvice— tránh khai báo trùng bean trong ứng dụng.