refactor(security): 重构安全配置并优化测试环境

- 移除旧的测试套件和UAT测试文件
- 更新密码编码器配置使用BCrypt strength=12
- 添加用户角色关联表和相关服务
- 优化前端日期显示格式
- 清理无用资源和配置文件
- 增强测试数据管理和清理功能
This commit is contained in:
张翔
2026-03-27 13:00:22 +08:00
parent ce30893a96
commit af44c23f21
294 changed files with 16057 additions and 22601 deletions
@@ -1,18 +1,26 @@
package cn.novalon.manage.app;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
@SpringBootApplication
@SpringBootApplication(exclude = {ReactiveUserDetailsServiceAutoConfiguration.class})
@ConfigurationPropertiesScan(basePackages = "cn.novalon.manage")
@ComponentScan(basePackages = "cn.novalon.manage")
@EnableR2dbcRepositories(basePackages = {"cn.novalon.manage.db.dao"})
public class ManageApplication {
private static final Logger logger = LoggerFactory.getLogger(ManageApplication.class);
public static void main(String[] args) {
logger.info("应用程序启动中...");
logger.info("包扫描路径: cn.novalon.manage");
SpringApplication.run(ManageApplication.class, args);
logger.info("应用程序启动完成");
}
}
@@ -0,0 +1,57 @@
package cn.novalon.manage.app.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* Jackson配置类
*
* 用于统一时间格式化配置
*
* @author 张翔
* @date 2026-03-26
*/
@Configuration
public class JacksonConfig {
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
JavaTimeModule javaTimeModule = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
objectMapper.registerModule(javaTimeModule);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
return objectMapper;
}
@Bean
public Jackson2JsonEncoder jackson2JsonEncoder(ObjectMapper objectMapper) {
return new Jackson2JsonEncoder(objectMapper);
}
@Bean
public Jackson2JsonDecoder jackson2JsonDecoder(ObjectMapper objectMapper) {
return new Jackson2JsonDecoder(objectMapper);
}
}
@@ -65,6 +65,8 @@ public class SystemRouter {
.POST("/api/users/restore", userHandler::restoreUsers)
.GET("/api/users/check/username", userHandler::checkUsernameExists)
.GET("/api/users/check/email", userHandler::checkEmailExists)
.POST("/api/users/{id}/roles", userHandler::assignRoles)
.GET("/api/users/{id}/roles", userHandler::getUserRoles)
.build();
}
@@ -14,9 +14,10 @@ spring:
max-idle-time: 30m
max-life-time: 1h
acquire-timeout: 5s
flyway:
enabled: true
locations: classpath:db/migration
security:
user:
name: disabled
password: disabled
management:
endpoints:
@@ -1,83 +0,0 @@
-- 测试数据初始化脚本
-- 用于E2E测试和UAT测试的测试数据生成
-- 1. 清理现有测试数据
DELETE FROM sys_user_role WHERE user_id IN (SELECT id FROM sys_user WHERE username LIKE 'test_%' OR username = 'admin');
DELETE FROM sys_role_menu WHERE role_id IN (SELECT id FROM sys_role WHERE role_key LIKE 'test_%' OR role_key = 'admin');
DELETE FROM sys_login_log WHERE username IN ('admin', 'test_user', 'test_admin');
DELETE FROM sys_user WHERE username IN ('admin', 'test_user', 'test_admin');
DELETE FROM sys_role WHERE role_key LIKE 'test_%' OR role_key = 'admin';
DELETE FROM sys_menu WHERE menu_name LIKE '测试%' OR menu_name = '系统管理';
-- 2. 插入测试角色
INSERT INTO sys_role (role_name, role_key, role_sort, status, create_by, create_time, update_by, update_time, remark) VALUES
('超级管理员', 'admin', 1, 1, 'system', NOW(), 'system', NOW(), '系统超级管理员,拥有所有权限'),
('普通用户', 'user', 2, 1, 'system', NOW(), 'system', NOW(), '普通用户,拥有基本权限'),
('测试管理员', 'test_admin', 3, 1, 'system', NOW(), 'system', NOW(), '测试用管理员角色'),
('测试普通用户', 'test_user', 4, 1, 'system', NOW(), 'system', NOW(), '测试用普通用户角色');
-- 3. 插入测试菜单
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) VALUES
('系统管理', 0, 1, 'system', NULL, 'M', '0', '0', '', 'system', 'system', NOW(), 'system', NOW(), '系统管理目录'),
('用户管理', 1, 1, 'user', 'system/user/index', 'C', '0', '0', 'system:user:list', 'user', 'system', NOW(), 'system', NOW(), '用户管理菜单'),
('角色管理', 1, 2, 'role', 'system/role/index', 'C', '0', '0', 'system:role:list', 'role', 'system', NOW(), 'system', NOW(), '角色管理菜单'),
('菜单管理', 1, 3, 'menu', 'system/menu/index', 'C', '0', '0', 'system:menu:list', 'menu', 'system', NOW(), 'system', NOW(), '菜单管理菜单'),
('审计日志', 0, 2, 'audit', NULL, 'M', '0', '0', '', 'audit', 'system', NOW(), 'system', NOW(), '审计日志目录'),
('登录日志', 5, 1, 'loginlog', 'audit/loginlog/index', 'C', '0', '0', 'audit:loginlog:list', 'loginlog', 'system', NOW(), 'system', NOW(), '登录日志菜单'),
('系统监控', 0, 3, 'monitor', NULL, 'M', '0', '0', '', 'monitor', 'system', NOW(), 'system', NOW(), '系统监控目录'),
('在线用户', 7, 1, 'online', 'monitor/online/index', 'C', '0', '0', 'monitor:online:list', 'online', 'system', NOW(), 'system', NOW(), '在线用户菜单');
-- 4. 插入测试用户
INSERT INTO sys_user (username, password, email, phone, status, create_by, create_time, update_by, update_time, remark) VALUES
('admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', 'admin@novalon.com', '13800138000', 1, 'system', NOW(), 'system', NOW(), '系统管理员'),
('test_user', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', 'testuser@novalon.com', '13800138001', 1, 'system', NOW(), 'system', NOW(), '测试普通用户'),
('test_admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', 'testadmin@novalon.com', '13800138002', 1, 'system', NOW(), 'system', NOW(), '测试管理员');
-- 5. 分配用户角色关系
INSERT INTO sys_user_role (user_id, role_id) VALUES
((SELECT id FROM sys_user WHERE username = 'admin'), (SELECT id FROM sys_role WHERE role_key = 'admin')),
((SELECT id FROM sys_user WHERE username = 'test_user'), (SELECT id FROM sys_role WHERE role_key = 'test_user')),
((SELECT id FROM sys_user WHERE username = 'test_admin'), (SELECT id FROM sys_role WHERE role_key = 'test_admin'));
-- 6. 分配角色菜单关系
-- 超级管理员拥有所有菜单权限
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT (SELECT id FROM sys_role WHERE role_key = 'admin'), id FROM sys_menu;
-- 普通用户只拥有用户查看权限
INSERT INTO sys_role_menu (role_id, menu_id) VALUES
((SELECT id FROM sys_role WHERE role_key = 'user'), (SELECT id FROM sys_menu WHERE menu_name = '系统管理')),
((SELECT id FROM sys_role WHERE role_key = 'user'), (SELECT id FROM sys_menu WHERE menu_name = '用户管理'));
-- 测试管理员拥有系统管理权限
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT (SELECT id FROM sys_role WHERE role_key = 'test_admin'), id FROM sys_menu WHERE menu_name IN ('系统管理', '用户管理', '角色管理', '菜单管理', '审计日志', '登录日志');
-- 测试普通用户拥有基本查看权限
INSERT INTO sys_role_menu (role_id, menu_id) VALUES
((SELECT id FROM sys_role WHERE role_key = 'test_user'), (SELECT id FROM sys_menu WHERE menu_name = '系统管理')),
((SELECT id FROM sys_role WHERE role_key = 'test_user'), (SELECT id FROM sys_menu WHERE menu_name = '用户管理'));
-- 7. 插入测试登录日志
INSERT INTO sys_login_log (username, ipaddr, login_location, browser, os, status, msg, login_time, create_by, create_time) VALUES
('admin', '127.0.0.1', '本地', 'Chrome 120.0', 'Mac OS X', 1, '登录成功', NOW(), 'system', NOW()),
('test_user', '127.0.0.1', '本地', 'Firefox 121.0', 'Windows 10', 1, '登录成功', NOW(), 'system', NOW()),
('test_admin', '127.0.0.1', '本地', 'Safari 17.0', 'Mac OS X', 1, '登录成功', NOW(), 'system', NOW()),
('admin', '192.168.1.100', '内网', 'Chrome 119.0', 'Windows 11', 1, '登录成功', NOW() - INTERVAL '1 hour', 'system', NOW() - INTERVAL '1 hour'),
('test_user', '192.168.1.101', '内网', 'Edge 120.0', 'Windows 10', 1, '登录成功', NOW() - INTERVAL '2 hours', 'system', NOW() - INTERVAL '2 hours');
-- 8. 验证测试数据
SELECT '测试用户数据' as data_type, COUNT(*) as count FROM sys_user WHERE username IN ('admin', 'test_user', 'test_admin')
UNION ALL
SELECT '测试角色数据', COUNT(*) FROM sys_role WHERE role_key IN ('admin', 'user', 'test_admin', 'test_user')
UNION ALL
SELECT '测试菜单数据', COUNT(*) FROM sys_menu WHERE menu_name IN ('系统管理', '用户管理', '角色管理', '菜单管理', '审计日志', '登录日志', '系统监控', '在线用户')
UNION ALL
SELECT '用户角色关系', COUNT(*) FROM sys_user_role WHERE user_id IN (SELECT id FROM sys_user WHERE username IN ('admin', 'test_user', 'test_admin'))
UNION ALL
SELECT '角色菜单关系', COUNT(*) FROM sys_role_menu WHERE role_id IN (SELECT id FROM sys_role WHERE role_key IN ('admin', 'user', 'test_admin', 'test_user'))
UNION ALL
SELECT '登录日志数据', COUNT(*) FROM sys_login_log WHERE username IN ('admin', 'test_user', 'test_admin');
-- 提交事务
COMMIT;