一、前期准备工作
本文方案适配绝大多数基于SpringBoot 2.x开发的自研/二开档案管理软件,运行要求为JDK8+、MySQL5.7+,其他技术栈核心逻辑通用,仅需对应调整语法即可。直接在项目的pom.xml中添加以下可复制依赖:
```xml
org.springframework.boot
spring-boot-starter-security
org.bouncycastle
bcprov-jdk15on
1.70
com.alibaba
fastjson
1.2.83
```
二、核心优化实操步骤
2.1 三级粒度权限控制配置
档案管理的核心风险是越权访问,本次实现菜单-文件夹-文件三级权限拦截,零越权,实操步骤:
```sql
-- 角色-文件夹权限关联表
CREATE TABLE `role_folder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_id` int(11) NOT NULL COMMENT '角色ID',
`folder_id` int(11) NOT NULL COMMENT '文件夹ID',
PRIMARY KEY (`id`),
KEY `idx_role_id` (`role_id`),
KEY `idx_folder_id` (`folder_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色文件夹权限关联表';
-- 角色-文件权限关联表
CREATE TABLE `role_file` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_id` int(11) NOT NULL COMMENT '角色ID',
`file_id` int(11) NOT NULL COMMENT '文件ID',
PRIMARY KEY (`id`),
KEY `idx_role_id` (`role_id`),
KEY `idx_file_id` (`file_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色文件权限关联表';
```
- 第二步:添加权限拦截AOP,修改包名后直接复制使用:
```java
@Aspect
@Component
public class FilePermissionAspect {
@Autowired
private RoleFolderService roleFolderService;
@Autowired
private RoleFileService roleFileService;
// 拦截文件夹访问请求
@Before("@annotation(com.yourpackage.anno.RequireFolderPerm) && args(.., folderId)")
public void checkFolderPermission(Integer folderId) throws Exception {
User currentUser = (User) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if(currentUser == null) throw new RuntimeException("无访问权限");
boolean hasPerm = roleFolderService.checkPerm(currentUser.getRoleList(), folderId);
if(!hasPerm) throw new RuntimeException("无该文件夹访问权限");
}
// 拦截文件访问请求
@Before("@annotation(com.yourpackage.anno.RequireFilePerm) && args(.., fileId)")
public void checkFilePermission(Integer fileId) throws Exception {
User currentUser = (User) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
boolean hasPerm = roleFileService.checkPerm(currentUser.getRoleList(), fileId);
if(!hasPerm) throw new RuntimeException("无该文件访问权限");
}
}
```
只需要在对应接口上添加权限注解即可自动拦截,未授权用户无法访问超出权限范围的档案。
2.2 传输存储全加密配置
- 第一步:开启HTTPS传输加密,在application.yml中添加完整配置:
```yaml
server:
port: 443
ssl:
enabled: true
key-store: classpath:your-domain.p12
key-store-password: 你的证书密码
key-store-type: PKCS12
```
免费SSL证书可按阿里云官方指引申请,地址:https://help.aliyun.com/document_detail/169861.html,导出为p12格式后放到项目resources目录即可。
- 第二步:实现文件存储加密,加密工具类直接复制使用:
```java
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
public class FileEncryptUtil {
// 替换为你自己的16位自定义密钥,例如:DANGAN2024SAFE123
private static final String SECRET_KEY = "替换为你的16位密钥";
public static byte[] encrypt(byte[] fileContent) throws Exception {
PBEKeySpec keySpec = new PBEKeySpec(SECRET_KEY.toCharArray(),
SECRET_KEY.getBytes(), 1024, 128);
SecretKey secretKey = SecretKeyFactory.getInstance("PBEWithMD5AndDES")
.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(fileContent);
}
public static byte[] decrypt(byte[] encryptedContent) throws Exception {
PBEKeySpec keySpec = new PBEKeySpec(SECRET_KEY.toCharArray(),
SECRET_KEY.getBytes(), 1024, 128);
SecretKey secretKey = SecretKeyFactory.getInstance("PBEWithMD5AndDES")
.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(encryptedContent);
}
}
```
文件上传时调用encrypt加密后存储,下载时调用decrypt解密返回,加密后的文件即使被窃取也无法打开。
2.3 全操作审计日志配置

所有操作留痕方便溯源,第一步执行SQL创建日志表:
```sql
CREATE TABLE `file_operation_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '操作人ID',
`user_name` varchar(64) DEFAULT NULL COMMENT '操作人姓名',
`file_id` int(11) DEFAULT NULL COMMENT '操作文件ID',
`op_type` varchar(32) NOT NULL COMMENT '操作类型:查看/下载/修改/删除',
`ip` varchar(32) NOT NULL COMMENT '操作IP',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_file_id` (`file_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='档案操作审计日志';
```
通过AOP统一记录日志,无需每个接口手动编写代码,只需要在需要记录的接口添加@OperationLog(type = "下载")注解即可自动入库。
2.4 异常访问拦截配置
防止暴力破解登录,在Spring Security配置类中添加以下配置:
```java
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 统计登录失败次数,10分钟过期
private com.google.common.cache.Cache
loginFailCache =
CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build();
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.formLogin()
.failureHandler((request, response, e) -> {
String ip = request.getRemoteAddr();
Integer count = loginFailCache.getOrDefault(ip, 0);
loginFailCache.put(ip, count + 1);
if(count + 1 >= 5) {
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("IP已锁定,10分钟后重试");
return;
}
response.getWriter().write("用户名或密码错误");
});
}
}
```
三、效果验证步骤
完成配置后按以下步骤验证全部生效:
- 使用低权限账号访问高权限档案,确认返回无权限提示
- 登录服务器查看存储的加密档案,确认无法直接打开
- 下载任意档案后查询日志表,确认操作记录已正常保存
- 连续5次输入错误密码,确认IP被锁定无法继续登录
以上全部步骤完成后,档案管理软件的安全控制即完成优化,所有核心风险点都已覆盖。