Article · 2021-11-19

Encrypting User Data in a Points Mall: A Practical Retrofit Guide

3. Technical Implementation

3.1 Field Analysis

Based on the data structure, identify fields that require encryption:

3.2 AES Encryption Utility

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class AesUtil {
    private static final String ALGORITHM = "AES";
    private static final String KEY = "1234567890abcdef"; // 16位密钥

    public static String encrypt(String value) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encrypted = cipher.doFinal(value.getBytes());
        return Base64.getEncoder().encodeToString(encrypted);
    }

    public static String decrypt(String encrypted) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decoded = Base64.getDecoder().decode(encrypted);
        byte[] original = cipher.doFinal(decoded);
        return new String(original);
    }
}

3.3 Implementing MyBatis TypeHandler

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class EncryptTypeHandler extends BaseTypeHandler<String> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        try {
            ps.setString(i, AesUtil.encrypt(parameter));
        } catch (Exception e) {
            throw new SQLException("Encryption failed", e);
        }
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        try {
            return AesUtil.decrypt(rs.getString(columnName));
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        try {
            return AesUtil.decrypt(rs.getString(columnIndex));
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        try {
            return AesUtil.decrypt(cs.getString(columnIndex));
        } catch (Exception e) {
            return null;
        }
    }
}

Using this with a MyBatis Mapper:

<result property="phone" column="phone" typeHandler="xxx.EncryptTypeHandler" />

3.4 Data Migration Script

Create a migration script to encrypt legacy data.

Basic steps:

Example:

List<User> users = userDao.findAll();
for (User user : users) {
    String encryptedPhone = AesUtil.encrypt(user.getPhone());
    userDao.updatePhone(user.getId(), encryptedPhone);
}

4. Results

After completing the encryption retrofit, the system operated normally with no perceptible user experience impact, while improving data security and successfully meeting subsequent security management requirements.


Throughout the process, the critical factor was establishing clear standards, following the encryption protocol, and ensuring component compatibility. In production, you might consider selective encryption by field category for more granular control.

© 2026 Yuxu Ge ·