1. 项目概述为什么若依框架需要一份安全自查清单若依RuoYi作为国内Java开发者圈子里普及度极高的开源后台管理系统脚手架其“开箱即用”的特性极大地加速了企业级应用的开发进程。无论是单体版、前后端分离版还是集成了工作流Flowable或微服务Cloud的版本它都提供了丰富的模块和代码生成器。然而也正是因为其“脚手架”的定位许多开发者包括我早期容易陷入一个思维误区认为框架本身是安全的或者默认配置就是最佳实践。这恰恰是最大的安全隐患。在实际的渗透测试和代码审计工作中我见过太多基于若依开发的项目因为开发者直接沿用默认配置或未理解框架的安全机制导致系统门户大开。攻击者几乎可以拿着公开的漏洞利用脚本“按图索骥”。这份清单正是源于我多次为团队项目做安全加固和应急响应后总结出的、开发者最容易忽略或误配的五个高危点。它不是一份全面的安全指南而是一份聚焦于“配置”和“常见漏洞”的实战检查单。目的是让你在开发、测试、上线前花上半小时快速过一遍堵住那些最容易被利用的缺口。2. 高危配置一脆弱的默认密码与未改动的密钥这是最经典也最致命的问题。若依框架为了演示方便内置了默认的管理员账号admin/admin123和默认的加密密钥。在正式环境中不修改它们等同于把家门钥匙放在门口的垫子下面。2.1 默认密码的危害与排查危害攻击者通过弱口令爆破或直接使用默认凭证可直通系统后台获得最高权限。后续的数据窃取、植入后门、横向渗透都将易如反掌。自查与修复步骤修改内置用户密码路径系统启动后必须立即使用admin/admin123登录。操作进入“系统管理” - “用户管理”找到admin用户点击“修改”。务必使用强密码建议12位以上包含大小写字母、数字、特殊字符。同时检查并禁用或删除其他测试账号如ry/123456。原理这不仅仅是改一个密码更是切断了一条最直接的攻击路径。许多自动化攻击脚本的第一步就是尝试默认口令。重置应用加密密钥关键文件ruoyi-common/src/main/resources/application.yml单体或各微服务模块的bootstrap.yml/application.yml。关键配置项查找token.secret、aes.secret、jwt.secret等配置。若依使用这些密钥进行Token签名、数据加密等。操作绝对不能使用源码中或网上示例里的默认值。必须使用强随机字符串替换。例如可以使用在线工具或命令行如openssl rand -base64 32生成一个足够长且随机的字符串。# 错误示例使用默认或简单密钥 token: secret: abcdefghijklmnopqrstuvwxyz0123456789 # 正确示例使用生成的强随机密钥 token: secret: L8q6Zc7NwV5pXk2H9jF1rT0yS3dE4bG7aMqPwJzKv注意事项修改密钥会导致所有已登录用户的Token失效需要在系统维护时段进行操作。修改后务必重启应用。实操心得我曾审计过一个项目其token.secret竟然是公司名的拼音。攻击者一旦通过其他信息泄露猜到密钥就可以伪造任意用户的登录态JWT Token实现“越权登录”。密钥的强度直接决定了会话安全的下限。3. 高危配置二过度暴露的接口与信息泄露若依集成了Swagger、Druid监控等优秀组件方便开发和调试。但在生产环境它们可能成为信息泄露的源头。3.1 Swagger API文档的未授权访问危害Swagger-ui页面暴露了所有Controller接口的路径、参数、甚至数据结构。攻击者无需阅读源码即可了解系统全部API并可以在此界面直接发起请求进行参数探测和漏洞测试。自查与修复生产环境必须禁用或严格鉴权方案一推荐环境隔离。在application-prod.yml中彻底关闭Swagger。# application-prod.yml swagger: enabled: false方案二IP/角色白名单。如果确有内部维护需要可通过Spring Security或拦截器配置只允许内网IP或特定管理员角色访问/swagger-ui.html、/v2/api-docs等路径。// 示例在Security配置中添加规则 http.authorizeRequests() .antMatchers(/swagger-ui.html).hasRole(admin) // 或 .hasIpAddress(192.168.1.0/24) .antMatchers(/webjars/**, /swagger-resources/**, /v2/api-docs).permitAll() // 静态资源可放行 .anyRequest().authenticated();3.2 Druid监控台未授权访问危害Druid连接池监控台功能强大可以查看SQL执行、Session监控、甚至执行Web URI。若未加保护攻击者不仅能窥探数据库操作还可能利用其功能进行更深层次的攻击。自查与修复强制添加登录验证Druid内置了登录验证功能生产环境必须启用。# application.yml spring: datasource: druid: stat-view-servlet: enabled: true login-username: your_admin_name # 必须修改 login-password: your_strong_password # 必须修改 allow: 127.0.0.1 # 可设置IP白名单为空则允许所有不推荐 deny: # 黑名单结合应用安全框架同样可以将/druid/**路径纳入Spring Security的管理范围实现更复杂的权限控制。避坑技巧不要仅仅依赖Druid的简单密码验证。在安全要求高的场景应将其访问路径纳入统一的应用权限管理体系并记录访问日志。我曾遇到一个案例攻击者通过搜索引擎的inurl:druid/index.html语法直接找到了暴露在公网的监控台并利用弱口令进入最终拖走了整个数据库的配置信息。4. 高危配置三不当的文件上传与目录遍历文件上传是Web应用的常见功能也是漏洞高发区。若依的通用上传下载组件如果配置不当会引入严重风险。4.1 文件上传漏洞的典型场景危害攻击者上传恶意文件如JSP、PHP Webshell或包含恶意脚本的HTML从而获取服务器命令执行权限。自查与修复要点白名单校验文件后缀这是最重要的防线。不要使用黑名单禁止某些后缀因为总有漏网之鱼。应只允许业务必需的后缀。// 示例在文件上传服务中强化校验 public void validateFile(MultipartFile file) { String originalFilename file.getOriginalFilename(); String suffix StringUtils.substringAfterLast(originalFilename, .).toLowerCase(); ListString allowedSuffixList Arrays.asList(jpg, jpeg, png, gif, pdf, doc, docx); if (!allowedSuffixList.contains(suffix)) { throw new RuntimeException(不允许上传此类型文件); } // 进一步检查文件魔数Magic Number防止伪造后缀 }重命名存储文件不要使用用户上传的文件名。应使用UUID等随机名称重命名避免路径遍历和覆盖攻击。设置独立的存储域名和目录将上传文件存储到与应用服务器分离的目录并通过Nginx/Apache等Web服务器以静态资源方式提供服务。关键配置该目录禁止脚本执行权限。# Nginx 配置示例禁止指定目录执行PHP、JSP等脚本 location ~* ^/upload/.*\.(php|jsp|asp|aspx)$ { deny all; }限制文件大小在application.yml中配置spring.servlet.multipart.max-file-size和max-request-size防止DoS攻击。4.2 路径遍历漏洞Directory Traversal危害攻击者通过构造包含../等特殊字符的文件路径参数访问或上传文件到服务器上的任意目录如读取/etc/passwd或覆盖系统文件。自查与修复规范化路径在代码中对所有用户输入的文件路径参数进行规范化处理并检查是否在允许的根目录之内。// 使用Apache Commons IO或JDK7的Paths API String userInputPath request.getParameter(filePath); String safeBaseDir /var/www/uploads/; File file new File(safeBaseDir, userInputPath); String canonicalPath file.getCanonicalPath(); // 获取规范路径 if (!canonicalPath.startsWith(new File(safeBaseDir).getCanonicalPath())) { throw new IllegalArgumentException(非法路径访问); }经验之谈我曾处理过一个漏洞开发者直接使用request.getParameter(fileName)拼接成服务器路径进行文件读取未做任何过滤。攻击者通过fileName../../../../etc/passwd成功读取了系统敏感文件。永远不要信任客户端传入的任何路径信息。5. 高危配置四失效或不当的访问控制越权漏洞越权漏洞垂直越权、水平越权是业务逻辑层面的致命伤。若依虽然提供了基于权限注解如PreAuthorize的框架但开发者若使用不当等于形同虚设。5.1 水平越权我能操作别人的数据场景用户A和用户B属于同一角色用户A通过修改请求参数如订单ID、用户ID能访问或操作用户B的数据。自查与修复服务层强制校验数据归属这是核心。在每一个涉及数据ID的操作方法中必须加入归属权判断。GetMapping(/order/{orderId}) PreAuthorize(ss.hasPermi(system:order:query)) // 角色权限校验 public AjaxResult getOrder(PathVariable Long orderId) { // 1. 根据orderId查询订单 Order order orderService.selectOrderById(orderId); // 2. 关键步骤校验当前登录用户是否有权查看此订单 Long currentUserId SecurityUtils.getUserId(); if (!currentUserId.equals(order.getUserId())) { throw new ServiceException(无权访问此订单信息); } // 3. 返回数据 return AjaxResult.success(order); }切记PreAuthorize注解只解决了“有没有这个权限点”的问题没解决“这个数据是不是你的”的问题。两者必须结合使用。5.2 垂直越权用户拥有了管理员权限场景普通用户通过某种方式如修改前端隐藏字段、直接调用API访问到了只属于管理员的接口或功能。自查与修复严格使用权限注解确保所有Controller方法都使用了PreAuthorize注解并指定了正确的权限字符串如PreAuthorize(ss.hasPermi(system:user:edit))。定期审计权限配置检查sys_menu表中的菜单和按钮权限配置是否准确确保没有将高权限的perms错误地分配给了低角色。不要依赖前端隐藏永远不要相信前端传来的角色ID、权限标识来做后端鉴权。后端必须从安全的上下文中如SecurityUtils重新获取当前用户的真实身份和权限进行判断。踩坑记录在一个快速开发的项目中为了赶进度开发者给一个“用户管理”的查询接口只加了PreAuthorize(ss.hasPermi(system:user:list))但忘记在服务层校验查询范围。导致任何有user:list权限的员工都能通过修改查询参数列出公司所有员工包括高管的敏感信息。权限注解是“门卫”数据归属校验是“房间锁”两者缺一不可。6. 高危配置五错误的安全依赖与默认配置框架依赖的第三方组件如Fastjson、Jackson、Log4j2或其默认配置可能自带安全漏洞。6.1 依赖组件漏洞管理危害像Log4j2这样的基础日志组件爆发高危漏洞如CVE-2021-44228时若项目中引入了有漏洞的版本且使用了危险配置如开启JNDI查找系统将面临远程代码执行的极端风险。自查与修复流程定期扫描与升级工具使用Maven插件如mvn versions:display-dependency-updates或专业的软件成分分析SCA工具如OWASP Dependency-Check、Snyk定期检查项目依赖。关注重点关注序列化库Fastjson、Jackson、日志库Log4j2、Logback、模板引擎Thymeleaf、FreeMarker、数据库驱动等核心组件的安全公告。若依框架本身的版本升级关注若依官方GitHub的Release和Security Advisories。及时将框架升级到已修复已知安全漏洞的版本。6.2 危险的默认序列化与反序列化配置危害若依默认使用Jackson进行JSON序列化。如果接口接收的参数是复杂的泛型或允许指定类名且配置不当可能触发不安全的反序列化。自查与修复全局配置Jackson在配置类中明确关闭有风险的特性。Configuration public class JacksonConfig { Bean public ObjectMapper objectMapper() { ObjectMapper mapper new ObjectMapper(); // 禁用通过JSON字符串反序列化时指定任意类的能力 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); // 明确指定序列化/反序列化的可见性 mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); // 如果使用Polymorphic Deserialization多态反序列化必须使用安全的JsonTypeInfo配置避免基于类名的反序列化。 return mapper; } }谨慎使用RequestBody MapString, Object或Object这类通用参数接收方式如果后续又使用类似JSON.parseObject(jsonString, User.class)的方式进行转换且类名来自用户输入风险极高。应尽量使用明确的DTO对象接收参数。核心原则保持依赖的“最小化”和“最新化”。非必要的依赖不引入必要的依赖及时更新到安全版本。对于框架的默认配置尤其是涉及数据解析、网络通信、命令执行的要抱有怀疑态度查阅官方安全文档进行加固。7. 构建持续的安全自查流程安全不是一次性的配置而应融入开发运维的全生命周期。以上五个高危点是一个起点你需要建立一个持续的流程。代码提交门禁在Git仓库配置pre-commit或pre-receive钩子使用静态代码分析工具如SonarQube、Fortify SCA扫描代码将“硬编码密码”、“不安全的反序列化”等规则作为强制检查项。CI/CD集成扫描在持续集成流水线中集成依赖漏洞扫描SCA和动态应用安全测试DAST工具。每次构建都自动生成安全报告。定期人工审计每季度或每次重大迭代后按照本清单进行人工走查。重点关注新增的接口、配置变更和引入的新组件。监控与响应确保应用日志尤其是认证、授权、文件操作、敏感数据访问日志被完整收集和监控。设置告警规则对异常登录、高频错误请求、敏感路径访问等行为进行实时告警。安全本质上是一种“成本”与“风险”的平衡。这份清单聚焦于那些“低成本、高收益”的加固点旨在用最小的改动消除最普遍的风险。真正的安全防御是一个纵深体系从网络、主机、应用到代码、数据、人员每一层都不可或缺。但对于使用若依框架的开发者而言先把这五个“地基”打牢已经能抵御绝大多数自动化攻击和常见的手工测试了。记住默认不代表安全方便不等于可靠。每一次不经意的“沿用默认”都可能为未来埋下一颗雷。