31 KiB
Design Document
Overview
本设计文档描述了用户企业认证、身份认证和员工CA二维码认证功能的技术实现方案。该功能将在现有的若依系统(Spring Boot 2.5.15 + MyBatis + Vue3)中添加认证能力,并实现基于认证状态的权限控制。
系统采用分层架构设计,包括:
- Controller层:处理HTTP请求和响应
- Service层:实现业务逻辑
- Mapper层:数据访问层
- Domain层:实体模型
- CA接口适配层:对接外部CA服务
企业认证方式
系统采用法人CA认证方式进行企业认证:
- 用户提交企业信息和法人身份信息(法人姓名、法人身份证号)
- 系统验证信息完整性和格式
- 系统通过CA接口适配层调用外部CA服务进行法人身份认证
- CA服务验证法人身份与企业的关联关系
- CA认证成功后自动通过企业认证,认证状态直接变为"已认证"
- 无需人工审核,实现自动化认证
Architecture
企业认证业务流程
graph TD
A[用户填写企业信息+法人身份信息] --> B[提交法人CA认证申请]
B --> C[系统验证信息完整性]
C -->|验证通过| D[调用CA服务进行法人认证]
C -->|验证失败| E[返回错误信息]
D --> F{CA认证结果}
F -->|认证成功| G[自动通过企业认证]
F -->|认证失败| H[返回CA错误信息]
G --> I[更新状态为"已认证"]
I --> J[记录CA认证ID和时间]
模块划分
ruoyi-system (系统模块)
├── domain
│ ├── UserEnterpriseVerification (用户企业认证实体)
│ ├── UserIdentityVerification (用户身份认证实体)
│ └── VerificationAuditLog (认证审核日志实体)
├── mapper
│ ├── UserEnterpriseVerificationMapper
│ ├── UserIdentityVerificationMapper
│ └── VerificationAuditLogMapper
├── service
│ ├── IUserVerificationService (认证服务接口)
│ └── impl
│ └── UserVerificationServiceImpl
└── controller (在ruoyi-admin中)
└── UserVerificationController
ruoyi-credit (员工管理模块)
├── domain
│ └── EmployeeQRCode (员工实名认证二维码实体)
├── mapper
│ └── EmployeeQRCodeMapper
├── service
│ ├── IEmployeeQRCodeService
│ └── impl
│ └── EmployeeQRCodeServiceImpl
├── ca
│ ├── CAServiceAdapter (CA服务适配器接口)
│ ├── impl
│ │ ├── MockCAServiceAdapter (Mock实现)
│ │ └── RealCAServiceAdapter (真实CA服务实现-预留)
│ └── config
│ └── CAServiceConfig (CA服务配置)
└── controller (在ruoyi-admin中)
└── EmployeeQRCodeController
ruoyi-common (通用模块)
├── utils
│ ├── IdCardValidator (身份证验证工具)
│ ├── QRCodeGenerator (二维码生成工具)
│ └── EncryptionUtil (加密工具)
└── interceptor
└── VerificationInterceptor (认证拦截器)
技术栈
- 后端框架: Spring Boot 2.5.15
- 持久层: MyBatis + MySQL
- 安全框架: Spring Security
- 加密算法: AES-256-GCM (身份证号), RSA (二维码签名)
- 二维码生成: ZXing
- 前端框架: Vue 3 + Element Plus
- HTTP客户端: Apache HttpClient (调用CA服务)
Components and Interfaces
1. 权限常量定义
public class VerificationPermissions {
// 认证查看权限
public static final String VIEW_ALL_VERIFICATION = "system:verification:view:all";
public static final String EXPORT_VERIFICATION = "system:verification:export";
}
2. 用户认证服务 (UserVerificationService)
接口定义
public interface IUserVerificationService {
// 企业认证 - 法人CA认证方式
AjaxResult submitEnterpriseVerificationWithLegalPersonCA(EnterpriseCAVerificationRequest request);
AjaxResult getEnterpriseVerificationStatus(Long userId);
// 身份认证
AjaxResult submitIdentityVerification(UserIdentityVerification verification);
AjaxResult getIdentityVerificationStatus(Long userId);
// 认证状态查询
boolean isUserFullyVerified(Long userId);
VerificationStatusDTO getUserVerificationStatus(Long userId);
// 企业认证管理
@PreAuthorize("hasAuthority('system:verification:view:all')")
List<UserEnterpriseVerification> listEnterpriseVerifications(VerificationQuery query);
@PreAuthorize("hasAuthority('system:verification:export')")
byte[] exportEnterpriseVerifications(VerificationQuery query);
}
法人CA认证请求对象
public class EnterpriseCAVerificationRequest {
private Long userId; // 用户ID
private String enterpriseName; // 企业名称
private String enterpriseCode; // 企业统一社会信用代码
private String legalPersonName; // 法人姓名
private String legalPersonIdCard; // 法人身份证号
private String businessLicense; // 营业执照URL(可选)
}
4. CA服务适配器 (CAServiceAdapter)
接口定义
public interface IEmployeeQRCodeService {
// 二维码生成
AjaxResult generateQRCode(Long employeeId);
byte[] getQRCodeImage(String qrCodeId);
// 二维码验证(调用CA服务)
QRCodeVerificationResult verifyQRCodeWithCA(String qrCodeData);
boolean isQRCodeValid(String qrCodeId);
}
二维码数据格式
public class EmployeeQRCodeData {
private Long employeeId; // 员工ID
private String realName; // 真实姓名
private String idCardNumber; // 身份证号(明文)
private Long timestamp; // 时间戳
}
4. CA服务适配器 (CAServiceAdapter)
接口定义
public interface CAServiceAdapter {
// 身份认证操作
IdentityVerificationResponse verifyIdentity(IdentityVerificationRequest request);
// 健康检查
boolean isServiceAvailable();
}
CA服务请求/响应格式
// 身份认证请求对象
public class IdentityVerificationRequest {
private String userId; // 用户ID或员工ID
private String realName; // 真实姓名
private String idCardNumber; // 身份证号
private String verificationType; // IDENTITY-身份认证, EMPLOYEE-员工认证, LEGAL_PERSON-法人认证
private String enterpriseName; // 企业名称(法人认证时使用)
private String enterpriseCode; // 企业统一社会信用代码(法人认证时使用)
}
// 身份认证响应对象
public class IdentityVerificationResponse {
private boolean success;
private String verificationId; // CA服务返回的认证ID
private String verificationStatus; // APPROVED-通过, REJECTED-拒绝
private String rejectReason; // 拒绝原因
private Date verificationTime;
private String errorCode;
private String errorMessage;
private Map<String, Object> additionalData; // 额外数据(如法人认证返回的企业信息)
}
5. 认证拦截器 (VerificationInterceptor)
@Component
public class VerificationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 检查当前用户的认证状态
// 如果访问需要认证的菜单但用户未认证,则拦截
// 超级管理员例外
}
}
Data Models
1. 用户企业认证表 (sys_user_enterprise_verification)
CREATE TABLE sys_user_enterprise_verification (
verification_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '认证ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
enterprise_name VARCHAR(200) NOT NULL COMMENT '企业名称',
enterprise_code VARCHAR(100) NOT NULL COMMENT '企业统一社会信用代码',
legal_person VARCHAR(100) COMMENT '法人代表',
legal_person_id_card VARCHAR(200) COMMENT '法人身份证号(加密)',
business_license VARCHAR(500) COMMENT '营业执照URL',
verification_status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '认证状态: PENDING-未认证, APPROVED-已认证, REJECTED-认证失败',
ca_verification_id VARCHAR(100) COMMENT 'CA服务返回的认证ID',
ca_verification_time DATETIME COMMENT 'CA认证时间',
audit_remark VARCHAR(500) COMMENT '备注',
create_by VARCHAR(64) COMMENT '创建者',
create_time DATETIME COMMENT '创建时间',
update_by VARCHAR(64) COMMENT '更新者',
update_time DATETIME COMMENT '更新时间',
INDEX idx_user_id (user_id),
INDEX idx_status (verification_status),
INDEX idx_enterprise_code (enterprise_code),
INDEX idx_ca_verification_id (ca_verification_id)
) COMMENT='用户企业认证表';
2. 用户身份认证表 (sys_user_identity_verification)
CREATE TABLE sys_user_identity_verification (
verification_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '认证ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
real_name VARCHAR(100) NOT NULL COMMENT '真实姓名',
id_card_number VARCHAR(200) NOT NULL COMMENT '身份证号(加密)',
verification_status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '认证状态: PENDING-未认证, APPROVED-已认证, REJECTED-认证失败',
ca_verification_id VARCHAR(100) COMMENT 'CA服务返回的认证ID',
reject_reason VARCHAR(500) COMMENT 'CA服务拒绝原因',
verification_time DATETIME COMMENT 'CA认证时间',
create_by VARCHAR(64) COMMENT '创建者',
create_time DATETIME COMMENT '创建时间',
update_by VARCHAR(64) COMMENT '更新者',
update_time DATETIME COMMENT '更新时间',
INDEX idx_user_id (user_id),
INDEX idx_status (verification_status),
INDEX idx_ca_verification_id (ca_verification_id)
) COMMENT='用户身份认证表';
3. 认证审核日志表 (sys_verification_audit_log)
CREATE TABLE sys_verification_audit_log (
log_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '日志ID',
verification_type VARCHAR(20) NOT NULL COMMENT '认证类型: ENTERPRISE-企业认证, IDENTITY-身份认证',
verification_id BIGINT NOT NULL COMMENT '认证记录ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
old_status VARCHAR(20) COMMENT '原状态',
new_status VARCHAR(20) NOT NULL COMMENT '新状态',
audit_remark VARCHAR(500) COMMENT '审核备注',
operator_id BIGINT NOT NULL COMMENT '操作人ID',
operator_name VARCHAR(100) COMMENT '操作人姓名',
operator_roles VARCHAR(200) COMMENT '操作人角色列表(逗号分隔)',
operation_time DATETIME NOT NULL COMMENT '操作时间',
INDEX idx_verification (verification_type, verification_id),
INDEX idx_user_id (user_id),
INDEX idx_operation_time (operation_time),
INDEX idx_operator_id (operator_id)
) COMMENT='认证审核日志表';
4. 员工实名认证二维码表 (dc_employee_qr_code)
CREATE TABLE dc_employee_qr_code (
qr_code_id VARCHAR(64) PRIMARY KEY COMMENT '二维码ID(UUID)',
employee_id BIGINT NOT NULL COMMENT '员工ID',
real_name VARCHAR(100) NOT NULL COMMENT '真实姓名',
id_card_number VARCHAR(18) NOT NULL COMMENT '身份证号',
generate_time DATETIME NOT NULL COMMENT '生成时间',
expiry_time DATETIME NOT NULL COMMENT '过期时间',
qr_code_status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '二维码状态: ACTIVE-有效, EXPIRED-已过期, USED-已使用',
verification_status VARCHAR(20) COMMENT '认证状态: PENDING-待认证, APPROVED-已认证, REJECTED-认证失败',
ca_verification_id VARCHAR(100) COMMENT 'CA服务返回的认证ID',
verification_time DATETIME COMMENT '认证时间',
INDEX idx_employee_id (employee_id),
INDEX idx_status (qr_code_status),
INDEX idx_expiry_time (expiry_time)
) COMMENT='员工实名认证二维码表';
5. CA服务配置表 (sys_ca_service_config)
CREATE TABLE sys_ca_service_config (
config_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '配置ID',
config_key VARCHAR(100) NOT NULL UNIQUE COMMENT '配置键',
config_value VARCHAR(500) NOT NULL COMMENT '配置值',
config_desc VARCHAR(200) COMMENT '配置描述',
is_encrypted TINYINT(1) DEFAULT 0 COMMENT '是否加密存储',
create_time DATETIME COMMENT '创建时间',
update_time DATETIME COMMENT '更新时间'
) COMMENT='CA服务配置表';
-- 初始化配置数据
INSERT INTO sys_ca_service_config (config_key, config_value, config_desc) VALUES
('ca.service.url', 'http://localhost:8080/mock-ca', 'CA服务接口地址'),
('ca.service.timeout', '30000', 'CA服务超时时间(毫秒)'),
('ca.service.app_id', 'ruoyi-system', 'CA服务应用ID'),
('ca.service.app_secret', 'mock-secret-key', 'CA服务应用密钥'),
('ca.service.enabled', 'true', 'CA服务是否启用'),
('ca.qrcode.validity_hours', '24', '二维码默认有效期(小时)');
7. 角色和权限初始化
-- 插入认证审核员角色
INSERT INTO sys_role (role_name, role_key, role_sort, status, del_flag, create_time, remark) VALUES
('认证审核员', 'verification_auditor', 3, '0', '0', NOW(), '负责审核企业认证申请');
-- 插入认证管理员角色
INSERT INTO sys_role (role_name, role_key, role_sort, status, del_flag, create_time, remark) VALUES
('认证管理员', 'verification_manager', 2, '0', '0', NOW(), '负责管理所有认证信息');
-- 插入认证相关菜单权限
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_time, remark) VALUES
('认证管理', 0, 5, 'verification', NULL, 1, 'M', '0', '0', NULL, 'shield', NOW(), '认证管理目录'),
('企业认证审核', (SELECT menu_id FROM sys_menu WHERE menu_name='认证管理'), 1, 'enterprise', 'system/verification/enterprise', 1, 'C', '0', '0', 'system:verification:audit:enterprise', 'building', NOW(), '企业认证审核菜单'),
('认证信息管理', (SELECT menu_id FROM sys_menu WHERE menu_name='认证管理'), 2, 'manage', 'system/verification/manage', 1, 'C', '0', '0', 'system:verification:manage', 'list', NOW(), '认证信息管理菜单');
-- 为认证审核员角色分配权限
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT r.role_id, m.menu_id
FROM sys_role r, sys_menu m
WHERE r.role_key = 'verification_auditor'
AND m.perms IN ('system:verification:audit:enterprise', 'system:verification:view:all');
-- 为认证管理员角色分配权限
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT r.role_id, m.menu_id
FROM sys_role r, sys_menu m
WHERE r.role_key = 'verification_manager'
AND m.perms IN ('system:verification:audit:enterprise', 'system:verification:manage', 'system:verification:view:all', 'system:verification:export');
Correctness Properties
属性是一个特征或行为,应该在系统的所有有效执行中保持为真——本质上是关于系统应该做什么的正式陈述。属性作为人类可读规范和机器可验证正确性保证之间的桥梁。
企业认证属性
Property 1: 企业认证信息验证 For any 企业认证申请,如果企业信息和法人身份信息完整且格式正确,则系统应该接受申请并返回成功 Validates: Requirements 1.2
Property 2: 法人CA认证调用 For any 有效的法人CA认证申请,系统应该通过CA接口适配层调用外部CA服务进行法人身份认证 Validates: Requirements 1.3
Property 3: 法人CA认证成功处理 For any CA服务返回法人认证成功的响应,系统应该自动通过企业认证并更新认证状态为"已认证" Validates: Requirements 1.4
Property 4: 法人CA认证失败处理 For any CA服务返回法人认证失败的响应,系统应该返回具体错误信息并保持认证状态为"未认证" Validates: Requirements 1.5
Property 5: 法人CA认证记录 For any 法人CA认证通过,系统应该记录CA认证ID、认证时间和法人身份信息 Validates: Requirements 1.6
Property 6: 企业认证重新申请 For any 被拒绝的企业认证,用户应该能够重新提交申请 Validates: Requirements 1.7
身份认证属性
Property 7: 身份证号格式验证 For any 18位身份证号,系统应该验证其格式和校验位的正确性 Validates: Requirements 2.4
Property 8: 身份证号加密存储 For any 有效的身份证号,存储后应该是加密的,且解密后应该等于原始值(round-trip property) Validates: Requirements 2.6, 7.1
Property 9: CA服务身份认证调用 For any 有效的身份认证申请,系统应该通过CA接口适配层调用外部CA服务进行身份认证 Validates: Requirements 2.5
Property 10: CA身份认证成功处理 For any CA服务返回认证成功的响应,系统应该更新认证状态为"已认证"并记录CA认证ID和时间 Validates: Requirements 2.6
Property 11: CA身份认证失败处理 For any CA服务返回认证失败的响应,系统应该更新认证状态为"认证失败"并记录拒绝原因 Validates: Requirements 2.7
员工实名认证二维码属性
Property 12: 二维码内容完整性 For any 员工,生成的实名认证二维码应该包含员工ID、真实姓名、身份证号和时间戳 Validates: Requirements 3.1
Property 13: 二维码CA认证调用 For any 有效的二维码,扫描后系统应该调用CA服务进行身份认证 Validates: Requirements 3.3
Property 14: 二维码认证成功处理 For any CA服务返回认证成功的响应,系统应该更新员工认证状态为"已认证"并记录认证时间 Validates: Requirements 3.4
Property 15: 二维码认证失败处理 For any CA服务返回认证失败的响应,系统应该返回具体失败原因并保持认证状态为"未认证" Validates: Requirements 3.5
Property 16: 二维码过期验证 For any 超过有效期的二维码,系统应该拒绝认证并提示重新生成 Validates: Requirements 3.6, 4.6
CA服务接口属性
Property 17: CA服务配置读取 For any CA服务调用,系统应该从配置文件读取接口地址和认证信息 Validates: Requirements 4.2
Property 18: CA服务错误处理 For any CA服务不可用的情况,系统应该返回友好的错误信息并记录日志 Validates: Requirements 4.3
Property 19: CA服务超时处理 For any CA服务调用,如果30秒内未响应,系统应该超时并返回错误信息 Validates: Requirements 4.6
Property 20: CA服务调用日志 For any CA服务调用,系统应该记录请求参数、响应结果和调用时间 Validates: Requirements 4.7
权限控制属性
Property 21: 未认证用户访问拦截 For any 未完成双认证的普通用户,访问需要认证的功能时应该被拦截并显示认证提示 Validates: Requirements 5.1, 5.3
Property 22: 双认证完成解除限制 For any 完成企业认证和身份认证的用户,应该能够访问所有需要认证的功能 Validates: Requirements 5.4
Property 23: 超级管理员特殊权限 For any 超级管理员用户(userId=1),即使未认证也应该能够访问所有功能 Validates: Requirements 5.5
Property 24: 权限检查双认证状态 For any 权限检查操作,系统应该验证用户的企业认证和身份认证状态都为"已认证" Validates: Requirements 5.8
Property 25: 认证菜单配置化 For any 配置为需要认证的菜单,系统应该根据配置文件进行权限控制 Validates: Requirements 5.9
数据安全属性
Property 26: 认证数据访问权限 For any 认证数据访问操作,系统应该验证用户权限并记录访问日志 Validates: Requirements 7.3
Property 27: 法人身份证号加密存储 For any 有效的法人身份证号,存储后应该是加密的,且解密后应该等于原始值(round-trip property) Validates: Requirements 7.1
Error Handling
1. 输入验证错误
- 企业信息不完整: 返回缺失字段列表
- 企业统一社会信用代码格式错误: 返回格式说明
- 身份证号格式错误: 返回格式说明和校验位错误提示
- 身份证号校验位错误: 返回校验位计算说明
2. 业务逻辑错误
- 重复提交认证申请: 提示已有待审核的申请
- 认证状态不允许操作: 提示当前状态和允许的操作
- 二维码已过期: 提示二维码已过期,需要重新生成
- 二维码签名验证失败: 提示二维码无效
3. 外部服务错误
- CA服务不可用: 返回友好提示,建议稍后重试,记录详细错误日志
- CA服务超时: 返回超时提示,记录超时日志
- CA服务返回错误: 解析错误码,返回对应的中文提示
4. 系统错误
- 加密/解密失败: 记录错误日志,返回通用错误提示
- 数据库操作失败: 记录错误日志,返回通用错误提示
- 二维码生成失败: 记录错误日志,返回生成失败提示
错误码设计
public enum VerificationErrorCode {
// 输入验证错误 (1000-1999)
INVALID_ENTERPRISE_INFO(1001, "企业信息不完整或格式错误"),
INVALID_ID_CARD_FORMAT(1002, "身份证号格式错误"),
INVALID_ID_CARD_CHECKSUM(1003, "身份证号校验位错误"),
// 业务逻辑错误 (2000-2999)
DUPLICATE_VERIFICATION(2001, "已有待审核的认证申请"),
INVALID_VERIFICATION_STATUS(2002, "当前认证状态不允许此操作"),
QRCODE_EXPIRED(2006, "二维码已过期"),
QRCODE_INVALID_SIGNATURE(2007, "二维码签名验证失败"),
// 外部服务错误 (3000-3999)
CA_SERVICE_UNAVAILABLE(3001, "CA服务暂时不可用,请稍后重试"),
CA_SERVICE_TIMEOUT(3002, "CA服务响应超时"),
CA_SERVICE_ERROR(3003, "CA服务返回错误"),
// 系统错误 (9000-9999)
ENCRYPTION_ERROR(9001, "数据加密失败"),
DECRYPTION_ERROR(9002, "数据解密失败"),
DATABASE_ERROR(9003, "数据库操作失败"),
QRCODE_GENERATION_ERROR(9004, "二维码生成失败");
private final int code;
private final String message;
VerificationErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
}
Testing Strategy
单元测试
使用JUnit 5进行单元测试,覆盖以下内容:
-
工具类测试
- IdCardValidator: 测试身份证号验证逻辑
- EncryptionUtil: 测试加密解密功能
- QRCodeGenerator: 测试二维码生成功能
-
Service层测试
- UserVerificationService: 测试认证业务逻辑
- EmployeeCACertificateService: 测试CA证书管理逻辑
- EmployeeQRCodeService: 测试二维码生成和验证逻辑
-
CA适配器测试
- MockCAServiceAdapter: 测试Mock实现
- CAServiceConfig: 测试配置读取
属性测试
使用jqwik进行属性测试,每个测试至少运行100次迭代:
-
认证属性测试
- 测试Property 1-8: 企业认证和身份认证的各种属性
- 生成随机的认证数据,验证系统行为
-
CA证书属性测试
- 测试Property 9-13: CA证书管理的各种属性
- 生成随机的员工和证书数据,验证证书生命周期
-
二维码属性测试
- 测试Property 14-18: 二维码生成和验证的各种属性
- 生成随机的二维码数据,验证签名和验证逻辑
-
权限控制属性测试
- 测试Property 23-27: 权限控制的各种属性
- 生成随机的用户和认证状态,验证权限拦截逻辑
-
加密属性测试
- 测试Property 7, 15, 28: 加密和签名的round-trip属性
- 生成随机的数据,验证加密解密和签名验证的正确性
集成测试
-
Controller层集成测试
- 使用MockMvc测试API接口
- 测试请求参数验证、响应格式、错误处理
-
数据库集成测试
- 使用H2内存数据库进行测试
- 测试Mapper层的CRUD操作
-
CA服务集成测试
- 使用MockCAServiceAdapter进行测试
- 测试CA服务调用、超时处理、错误处理
前端测试
-
组件测试
- 使用Vitest测试Vue组件
- 测试认证表单、认证状态显示、二维码显示
-
E2E测试
- 使用Playwright测试完整的认证流程
- 测试用户提交认证、管理员审核、权限控制
测试覆盖率目标
- 单元测试代码覆盖率: ≥ 80%
- 属性测试: 覆盖所有定义的正确性属性
- 集成测试: 覆盖所有API接口
- E2E测试: 覆盖主要业务流程
Implementation Notes
1. 加密实现
使用BouncyCastle库实现AES-256-GCM加密:
public class EncryptionUtil {
private static final String ALGORITHM = "AES/GCM/NoPadding";
private static final int GCM_TAG_LENGTH = 128;
private static final int GCM_IV_LENGTH = 12;
public static String encrypt(String plaintext, SecretKey key) {
// 实现AES-256-GCM加密
}
public static String decrypt(String ciphertext, SecretKey key) {
// 实现AES-256-GCM解密
}
}
2. 身份证号验证
实现GB 11643-1999标准的身份证号验证:
public class IdCardValidator {
private static final int[] WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
private static final char[] CHECK_CODE = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
public static boolean validate(String idCard) {
// 验证长度、格式、校验位
}
}
3. 二维码生成
使用ZXing库生成二维码:
public class QRCodeGenerator {
public static byte[] generateQRCode(String content, int width, int height) {
// 使用ZXing生成二维码图片
}
}
4. CA服务适配器配置
在application.yml中配置CA服务:
ca:
service:
enabled: true
adapter: mock # mock 或 real
url: http://localhost:8080/mock-ca
timeout: 30000
app-id: ruoyi-system
app-secret: ${CA_APP_SECRET:mock-secret-key}
certificate:
validity-days: 365
qrcode:
validity-hours: 24
5. 权限拦截器配置
在WebMvcConfigurer中注册拦截器:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private VerificationInterceptor verificationInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(verificationInterceptor)
.addPathPatterns("/credit/contract/**") // 需要认证的路径
.excludePathPatterns("/system/user/verification/**"); // 排除认证接口本身
}
}
6. 定时任务
使用Spring的@Scheduled注解实现CA证书过期提醒:
@Component
public class CertificateExpiryTask {
@Scheduled(cron = "0 0 9 * * ?") // 每天早上9点执行
public void checkExpiringCertificates() {
// 查询30天内过期的证书
// 发送过期提醒通知
}
}
7. 前端界面实现
企业认证提交
<template>
<el-dialog title="企业认证" v-model="dialogVisible">
<!-- 法人CA认证表单 -->
<el-form :model="caForm" ref="caFormRef">
<el-form-item label="企业名称" prop="enterpriseName" required>
<el-input v-model="caForm.enterpriseName" />
</el-form-item>
<el-form-item label="统一社会信用代码" prop="enterpriseCode" required>
<el-input v-model="caForm.enterpriseCode" />
</el-form-item>
<el-form-item label="法人姓名" prop="legalPersonName" required>
<el-input v-model="caForm.legalPersonName" />
</el-form-item>
<el-form-item label="法人身份证号" prop="legalPersonIdCard" required>
<el-input v-model="caForm.legalPersonIdCard" maxlength="18" />
</el-form-item>
<el-form-item label="营业执照" prop="businessLicense">
<el-upload action="/api/upload" :on-success="handleUploadSuccess">
<el-button>上传营业执照(可选)</el-button>
</el-upload>
</el-form-item>
<el-alert
title="法人CA认证说明"
type="info"
:closable="false"
description="系统将通过CA服务验证法人身份与企业的关联关系,认证成功后自动完成企业认证。"
/>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitVerification" :loading="submitting">
提交认证
</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { submitEnterpriseVerificationWithCA } from '@/api/verification';
const caForm = ref({
enterpriseName: '',
enterpriseCode: '',
legalPersonName: '',
legalPersonIdCard: '',
businessLicense: ''
});
const submitVerification = async () => {
await submitEnterpriseVerificationWithCA(caForm.value);
};
</script>
在Vue Router中添加路由守卫:
router.beforeEach(async (to, from, next) => {
if (to.meta.requiresVerification) {
const verificationStatus = await getVerificationStatus();
if (!verificationStatus.isFullyVerified && !verificationStatus.isSuperAdmin) {
// 显示认证提示横幅
showVerificationBanner();
// 阻止访问
next(false);
} else {
next();
}
} else {
next();
}
});
8. 前端路由守卫
在Vue Router中添加路由守卫:
router.beforeEach(async (to, from, next) => {
if (to.meta.requiresVerification) {
const verificationStatus = await getVerificationStatus();
if (!verificationStatus.isFullyVerified && !verificationStatus.isSuperAdmin) {
// 显示认证提示横幅
showVerificationBanner();
// 阻止访问
next(false);
} else {
next();
}
} else {
next();
}
});
Deployment Considerations
1. 数据库迁移
使用Flyway或Liquibase管理数据库版本:
- V1__create_verification_tables.sql: 创建认证相关表
- V2__create_ca_certificate_tables.sql: 创建CA证书相关表
- V3__init_ca_service_config.sql: 初始化CA服务配置
2. 密钥管理
- AES加密密钥: 使用环境变量或密钥管理服务(如AWS KMS)
- RSA密钥对: 生成后安全存储,定期轮换
- CA服务密钥: 加密存储在配置表中
3. 性能优化
- 认证状态缓存: 使用Redis缓存用户认证状态,减少数据库查询
- 二维码图片缓存: 缓存生成的二维码图片
- CA服务调用: 实现重试机制和熔断器
4. 监控和告警
- CA服务可用性监控
- 证书过期监控
- 认证申请量监控
- 错误率监控
5. 安全加固
- 限制认证申请频率(防止滥用)
- 审核操作需要二次确认
- 敏感操作记录审计日志
- 定期备份认证数据