Chuyển tới nội dung chính

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ụcVai trò
EncryptServiceInterface mã hoá/giải mã; implementation mặc định nằm ở govex-cloud-config (AES, khoá từ setting security.aes_secret)
DecryptRequestBodyAdviceBean 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
EncryptionModuleJackson module xử lý @JsonPropertyEncrypt; tạo qua EncryptionModule.serializerEncrypt(), deserializerDecrypt()...
Session attribute IAM_ENCRYPT_SECRETKhoá 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 EncryptServiceDecryptRequestBodyAdvice thì tính năng mới hoạt động đầy đủ.
  • @DecryptRequestBody gắn trên tham số kèm @RequestBody; luồng đăng nhập phải thiết lập session attribute IAM_ENCRYPT_SECRET trướ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ủa EncryptionModule trả 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 (package vn.govex.cloud.api.jackson) hỗ trợ chọn chiều xử lý qua serializer/deserializer với JsonEncryptType (ENCRYPT, DECRYPT, NONE); mặc định serializer ENCRYPT, deserializer DECRYPT.
  • govex-cloud-security đã đăng ký sẵn DecryptRequestBodyAdvice — tránh khai báo trùng bean trong ứng dụng.