diff --git a/README.md b/README.md index 2477de99d0..cebe6ef371 100644 --- a/README.md +++ b/README.md @@ -6,36 +6,45 @@ * 前端采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)。 * 后端采用 Spring Boot、MySQL、Redis。 -* 权限认证使用 Spring Security & JWT,支持多终端认证系统。 +* 权限认证使用 Spring Security & Token,支持多终端认证系统。 * 支持加载动态权限菜单,多方式轻松权限控制。 * 高效率开发,使用代码生成器可以一键生成前后端代码。 ## 内置功能 -分成 **业务** 和 **技术** 两类内置功能。 +分成三种内置功能: +* 系统功能 +* 基础设施 +* 研发工具 -### 业务功能 +### 系统功能 -1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 -2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 -3. 岗位管理:配置系统用户所属担任职务。 -4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 -5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 -6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 -7. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 -8. 登录日志:系统登录日志记录查询包含登录异常。 -9. 在线用户:当前系统中活跃用户状态监控。 -10. 通知公告:系统通知公告信息发布维护。 +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置 +1. 在线用户:当前系统中活跃用户状态监控 +1. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分 +1. 菜单管理:配置系统菜单,操作权限,按钮权限标识等 +1. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 +1. 岗位管理:配置系统用户所属担任职务 +1. 字典管理:对系统中经常使用的一些较为固定的数据进行维护 +1. 通知公告:系统通知公告信息发布维护 +1. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询 +1. 登录日志:系统登录日志记录查询包含登录异常 -## 技术功能 +### 基础设施 -1. 配置管理:对系统动态配置常用参数。 -2. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 -3. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 -4. 系统接口:根据业务代码自动生成相关的api接口文档。 -5. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 -6. 在线构建器:拖动表单元素生成相应的HTML代码。 -7. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 +1. 配置管理:对系统动态配置常用参数 +1. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志 +1. MySQL 监控:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 +1. Redis 监控:监控 Redis 数据库的使用情况,使用的 Redis Key 管理 +1. Java 监控:基于 Spring Boot Admin 实现 Java 应用的监控 +1. 链路追踪:基于 SkyWalking 实现性能监控,特别是链路的追踪 + +### 研发工具 + +1. 表单构建:拖动表单元素生成相应的 HTML 代码 +1. 代码生成:前后端代码的生成(Java、Vue、SQL),支持 CRUD 下载 +1. 系统接口:基于 Swagger 自动生成相关的 RESTful API 接口文档 +1. 数据库文档:基于 Screw 自动生成数据库文档 ## 在线体验 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/FilterConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/FilterConfig.java deleted file mode 100644 index 89f2e3150f..0000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/config/FilterConfig.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.ruoyi.framework.config; - -import java.util.HashMap; -import java.util.Map; -import javax.servlet.DispatcherType; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import com.ruoyi.common.filter.RepeatableFilter; -import com.ruoyi.common.filter.XssFilter; -import com.ruoyi.common.utils.StringUtils; - -/** - * Filter配置 - * - * @author ruoyi - */ -@Configuration -public class FilterConfig { - @Value("${xss.enabled}") - private String enabled; - - @Value("${xss.excludes}") - private String excludes; - - @Value("${xss.urlPatterns}") - private String urlPatterns; - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Bean - public FilterRegistrationBean xssFilterRegistration() { - FilterRegistrationBean registration = new FilterRegistrationBean(); - registration.setDispatcherTypes(DispatcherType.REQUEST); - registration.setFilter(new XssFilter()); - registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); - registration.setName("xssFilter"); - registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); - Map initParameters = new HashMap(); - initParameters.put("excludes", excludes); - initParameters.put("enabled", enabled); - registration.setInitParameters(initParameters); - return registration; - } - -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java deleted file mode 100644 index 14954125cc..0000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.ruoyi.common.filter; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import com.ruoyi.common.utils.StringUtils; - -/** - * 防止XSS攻击的过滤器 - * - * @author ruoyi - */ -public class XssFilter implements Filter -{ - /** - * 排除链接 - */ - public List excludes = new ArrayList<>(); - - /** - * xss过滤开关 - */ - public boolean enabled = false; - - @Override - public void init(FilterConfig filterConfig) throws ServletException - { - String tempExcludes = filterConfig.getInitParameter("excludes"); - String tempEnabled = filterConfig.getInitParameter("enabled"); - if (StringUtils.isNotEmpty(tempExcludes)) - { - String[] url = tempExcludes.split(","); - for (int i = 0; url != null && i < url.length; i++) - { - excludes.add(url[i]); - } - } - if (StringUtils.isNotEmpty(tempEnabled)) - { - enabled = Boolean.valueOf(tempEnabled); - } - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException - { - HttpServletRequest req = (HttpServletRequest) request; - HttpServletResponse resp = (HttpServletResponse) response; - if (handleExcludeURL(req, resp)) - { - chain.doFilter(request, response); - return; - } - XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); - chain.doFilter(xssRequest, response); - } - - private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) - { - if (!enabled) - { - return true; - } - if (excludes == null || excludes.isEmpty()) - { - return false; - } - String url = request.getServletPath(); - for (String pattern : excludes) - { - Pattern p = Pattern.compile("^" + pattern); - Matcher m = p.matcher(url); - if (m.find()) - { - return true; - } - } - return false; - } - - @Override - public void destroy() - { - - } -} \ No newline at end of file diff --git a/ruoyi-common/src/main/resources/application.yml b/ruoyi-common/src/main/resources/application.yml index 8adc0a845d..24c97bc132 100644 --- a/ruoyi-common/src/main/resources/application.yml +++ b/ruoyi-common/src/main/resources/application.yml @@ -33,12 +33,3 @@ logging: level: com.ruoyi: debug org.springframework: warn - -# 防止XSS攻击 -xss: - # 过滤开关 - enabled: true - # 排除链接(多个用逗号分隔) - excludes: /system/notice/* - # 匹配链接 - urlPatterns: /system/*,/monitor/*,/tool/* diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java b/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java index c03ee9e8a2..d7780ed9b7 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java +++ b/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java @@ -1,6 +1,8 @@ package cn.iocoder.dashboard.framework.web.core.filter; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HTMLFilter; @@ -14,6 +16,7 @@ import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Map; /** * Xss 请求 Wrapper @@ -36,7 +39,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { super(request); } - private static String filterHtml(String content) { + private static String filterXss(String content) { if (StrUtil.isEmpty(content)) { return content; } @@ -59,7 +62,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { // 读取内容,并过滤 String content = IoUtil.readUtf8(super.getInputStream()); - content = filterHtml(content); + content = filterXss(content); final ByteArrayInputStream newInputStream = new ByteArrayInputStream(content.getBytes()); // 返回 ServletInputStream return new ServletInputStream() { @@ -87,6 +90,47 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { // ========== Param 相关 ========== + @Override + public String getParameter(String name) { + String value = super.getParameter(name); + return filterXss(value); + } + + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (ArrayUtil.isEmpty(values)) { + return values; + } + // 过滤处理 + for (int i = 0; i < values.length; i++) { + values[i] = filterXss(values[i]); + } + return values; + } + + @Override + public Map getParameterMap() { + Map valueMap = super.getParameterMap(); + if (CollUtil.isEmpty(valueMap)) { + return valueMap; + } + // 过滤处理 + for (Map.Entry entry : valueMap.entrySet()) { + String[] values = entry.getValue(); + for (int i = 0; i < values.length; i++) { + values[i] = filterXss(values[i]); + } + } + return valueMap; + } + // ========== Header 相关 ========== + @Override + public String getHeader(String name) { + String value = super.getHeader(name); + return filterXss(value); + } + } diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index 65a1645dfd..0411782268 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -87,6 +87,7 @@ apollo: management: endpoints: web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator exposure: include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 @@ -131,3 +132,8 @@ yudao: codegen: base-package: ${yudao.info.base-package}.modules db-schemas: ${spring.datasource.name} + xss: + enable: true + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index 3947db18d0..845d24488c 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -87,6 +87,7 @@ apollo: management: endpoints: web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator exposure: include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 @@ -131,3 +132,8 @@ yudao: codegen: base-package: ${yudao.info.base-package}.modules db-schemas: ${spring.datasource.name} + xss: + enable: true + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求