Spring Boot3.3 項目數(shù)據(jù)庫連接使用SM4國密加密算法進行脫敏配置
在現(xiàn)代企業(yè)級應用開發(fā)中,數(shù)據(jù)安全問題越來越受到重視。尤其是在處理敏感信息如數(shù)據(jù)庫連接字符串、用戶名、密碼以及用戶個人信息(如身份證號)時,如何在保證系統(tǒng)功能正常的前提下對這些敏感數(shù)據(jù)進行有效的保護,已經(jīng)成為了開發(fā)人員必須面對的挑戰(zhàn)。本文將通過一個實際的Spring Boot項目案例,介紹如何使用國密SM4加密算法對數(shù)據(jù)庫連接中的url、username和password等信息進行加密處理,同時對用戶表中的身份證號等敏感數(shù)據(jù)進行脫敏顯示。
本文將詳細展示如何配置Spring Boot項目以支持SM4加密算法,如何編寫代碼實現(xiàn)數(shù)據(jù)加密和解密,以及如何結合MyBatis-Plus實現(xiàn)數(shù)據(jù)庫的CRUD操作,并在前端頁面進行數(shù)據(jù)的展示與脫敏處理。我們將從配置文件的加密解密、后端服務的實現(xiàn)到前端視圖的展示,逐步引導讀者構建一個完整的、注重數(shù)據(jù)安全的Spring Boot項目。
運行效果:
圖片
若想獲取項目完整代碼以及其他文章的項目源碼,且在代碼編寫時遇到問題需要咨詢交流,歡迎加入下方的知識星球。
表的DDL語句和插入數(shù)據(jù)的SQL語句
首先,我們需要創(chuàng)建一個user表,并插入10條用戶數(shù)據(jù)。
-- 創(chuàng)建user表
CREATE TABLE user (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
id_number VARCHAR(18) NOT NULL,
email VARCHAR(50) NOT NULL,
phone VARCHAR(15) NOT NULL,
address VARCHAR(100)
);
-- 插入10條用戶數(shù)據(jù)
INSERT INTO user (name, id_number, email, phone, address) VALUES
('張三', '110101199001011234', 'zhangsan@example.com', '13800138000', '北京市朝陽區(qū)'),
('李四', '110102199002021234', 'lisi@example.com', '13800138001', '北京市海淀區(qū)'),
('王五', '110103199003031234', 'wangwu@example.com', '13800138002', '北京市西城區(qū)'),
('趙六', '110104199004041234', 'zhaoliu@example.com', '13800138003', '北京市東城區(qū)'),
('錢七', '110105199005051234', 'qianqi@example.com', '13800138004', '北京市豐臺區(qū)'),
('孫八', '110106199006061234', 'sunba@example.com', '13800138005', '北京市石景山區(qū)'),
('周九', '110107199007071234', 'zhoujiu@example.com', '13800138006', '北京市通州區(qū)'),
('吳十', '110108199008081234', 'wushi@example.com', '13800138007', '北京市大興區(qū)'),
('鄭十一', '110109199009091234', 'zhengshiyi@example.com', '13800138008', '北京市昌平區(qū)'),
('王十二', '110110199010101234', 'wangshier@example.com', '13800138009', '北京市房山區(qū)');
引入SM4國密加密算法的依賴
在Spring Boot項目中,我們首先需要在pom.xml文件中引入必要的依賴。
<?xml versinotallow="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.icoderoad</groupId>
<artifactId>SM4Encryption</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SM4Encryption</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<mybatis-spring.version>3.0.3</mybatis-spring.version>
<mybatis-plus-boot-starter.version>3.5.7</mybatis-plus-boot-starter.version>
<aliyun-java-sdk-cor.version>4.5.0</aliyun-java-sdk-cor.version>
<bootstrap.version>5.1.3</bootstrap.version>
<jquery.version>3.6.0</jquery.version>
</properties>
<dependencies>
<!-- Spring Boot 依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 數(shù)據(jù)庫驅(qū)動依賴 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis-Plus 依賴 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!-- SM4 加密算法依賴 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>${aliyun-java-sdk-cor.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Thymeleaf 依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Bootstrap 和 jQuery -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>${bootstrap.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>${jquery.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置SM4加密算法
在application.yml文件中,我們可以配置SM4加密的相關參數(shù)。
sm4:
key: "37507d4cb936fdfb5dbb12a9a3983733" # SM4加密的密鑰
iv: "a7ae2a65d41fa7f98aec3579b8ec5a3c" # SM4的初始化向量
algorithm: "SM4" # 加密算法
mode: "CBC" # 工作模式
padding: "PKCS5Padding" # 填充模式
spring:
datasource:
url: ENC(sXjrlmJi+pBmt5ViI6uLAJ+teKmEfIPoJ5INkHEO2NtWcQ53zdATRyC4X+jru45oiaPjE74e+uLPgY/jHFy21iCVRnNpOFh5fHxn6NgF+04=)
username: ENC(vB/qydt/80xm7Dxu48i/mA==)
password: ENC(vB/qydt/80xm7Dxu48i/mA==)
實現(xiàn)SM4加密和解密工具類
package com.icoderoad.SM4Encryption.util;
import java.security.Security;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.Base64Utils;
public class SM4Util {
static {
Security.addProvider(new BouncyCastleProvider());
}
private static final String ALGORITHM_NAME = "SM4";
private static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";
/**
* SM4加密
* @param plainText 明文
* @param key 密鑰
* @param iv 向量
* @return 加密后的密文
*/
public static String encrypt(String plainText, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING);
SecretKeySpec keySpec = createKey(key);
IvParameterSpec ivSpec = createIv(iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* SM4解密
* @param cipherText 密文
* @param key 密鑰
* @param iv 向量
* @return 解密后的明文
*/
public static String decrypt(String cipherText, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING);
if (cipherText.startsWith("ENC(") && cipherText.endsWith(")")) {
cipherText = cipherText.substring(4, cipherText.length() - 1);
}
SecretKeySpec keySpec = createKey(key);
IvParameterSpec ivSpec = createIv(iv);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(decrypted);
}
private static SecretKeySpec createKey(String key) {
byte[] keyBytes = key.getBytes();
byte[] finalKey = new byte[16];
System.arraycopy(keyBytes, 0, finalKey, 0, Math.min(keyBytes.length, 16));
return new SecretKeySpec(finalKey, "SM4");
}
private static IvParameterSpec createIv(String iv) {
byte[] ivBytes = iv.getBytes();
byte[] finalIv = new byte[16];
System.arraycopy(ivBytes, 0, finalIv, 0, Math.min(ivBytes.length, 16));
return new IvParameterSpec(finalIv);
}
}
在項目中應用SM4加密
生成加密后的值
為了生成加密后的url、username和password,可以使用以下測試代碼來生成這些值。
package com.icoderoad.SM4Encryption;
import com.icoderoad.SM4Encryption.util.SM4Util;
public class SM4EncryptionTest {
public static void main(String[] args) throws Exception {
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false";
String username = "root";
String password = "root";
String key = "37507d4cb936fdfb5dbb12a9a3983733";
String iv = "a7ae2a65d41fa7f98aec3579b8ec5a3c";
System.out.println("加密后的URL: " + SM4Util.encrypt(url, key, iv));
System.out.println("加密后的用戶名: " + SM4Util.encrypt(username, key, iv));
System.out.println("加密后的密碼: " + SM4Util.encrypt(password, key, iv));
}
}
運行上述代碼后,得到加密后的url、username和password,將這些值更新到application.yml中。
我們可以在Spring Boot項目中使用@Value注解將加密后的數(shù)據(jù)庫密碼解密并應用于數(shù)據(jù)源配置。
package com.icoderoad.SM4Encryption.conf;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.icoderoad.SM4Encryption.util.SM4Util;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.url}")
private String encryptedUrl;
@Value("${spring.datasource.username}")
private String encryptedUsername;
@Value("${spring.datasource.password}")
private String encryptedPassword;
@Value("${sm4.key}")
private String key;
@Value("${sm4.iv}")
private String iv;
@Bean
public DataSource dataSource() throws Exception {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(SM4Util.decrypt(encryptedUrl, key, iv));
dataSource.setUsername(SM4Util.decrypt(encryptedUsername, key, iv));
dataSource.setPassword(SM4Util.decrypt(encryptedPassword, key, iv));
return dataSource;
}
}
User實體類
package com.icoderoad.SM4Encryption.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
private String idNumber;
private String email;
private String phone;
private String address;
@TableField(exist = false)
private String sensitiveIdNumber;
public String getSensitiveIdNumber() {
return idNumber.replaceAll("(\\d{6})\\d{8}(\\d{4})", "$1****$2");
}
}
UserMapper接口
package com.icoderoad.SM4Encryption.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.icoderoad.SM4Encryption.entity.User;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
UserService接口
package com.icoderoad.SM4Encryption.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.icoderoad.SM4Encryption.entity.User;
public interface UserService extends IService<User> {
}
UserServiceImpl類
package com.icoderoad.SM4Encryption.service.impl;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icoderoad.SM4Encryption.entity.User;
import com.icoderoad.SM4Encryption.mapper.UserMapper;
import com.icoderoad.SM4Encryption.service.UserService;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
我們需要創(chuàng)建一個控制器類來處理前端視圖頁面的請求,并將數(shù)據(jù)傳遞給視圖頁面進行展示。
UserController類
package com.icoderoad.SM4Encryption.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.icoderoad.SM4Encryption.entity.User;
import com.icoderoad.SM4Encryption.service.UserService;
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/")
public String listUsers(Model model) {
List<User> users = userService.list();
model.addAttribute("users", users);
return "index";
}
}
前端展示頁面與數(shù)據(jù)脫敏
前端頁面使用Thymeleaf模板引擎,并結合Bootstrap進行數(shù)據(jù)展示和脫敏處理。
在 src/main/resources/templates/index.html 中創(chuàng)建一個簡單的前端頁面:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用戶數(shù)據(jù)</title>
<link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.bundle.min.js"></script>
<style>
.container{
text-align: center;
}
thead th {
background-color: #007bff;
color: white;
}
tbody tr:nth-child(even) {
background-color: #f8f9fa;
}
.table {
margin: 20px auto;
width: 80%;
}
tr{
height: 30px;
}
</style>
</head>
<body>
<div class="container mt-5">
<h2>用戶數(shù)據(jù)</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>身份證號</th>
<th>郵箱</th>
<th>電話</th>
<th>地址</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.sensitiveIdNumber}"></td>
<td th:text="${user.email}"></td>
<td th:text="${user.phone}"></td>
<td th:text="${user.address}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
總結
本文通過實際案例,詳細介紹了如何在Spring Boot項目中使用SM4國密加密算法對數(shù)據(jù)庫連接信息和用戶數(shù)據(jù)進行加密與脫敏處理。我們展示了如何配置加密和解密操作,結合MyBatis-Plus實現(xiàn)數(shù)據(jù)庫操作,并通過Thymeleaf和Bootstrap構建前端頁面進行安全展示。
通過本文,大家可以掌握如何在Spring Boot中集成加密算法,并將其應用于實際項目中,提升數(shù)據(jù)安全性。希望本文為大家在處理敏感信息時提供了實用的指導,幫助構建更安全的企業(yè)級應用程序。