Commit 507f55f3c922219a2991e27bb532b4043a084454
1 parent
593e14f3
1. Xss 的完成
2. 完善 README 文档
Showing
7 changed files
with
92 additions
and
180 deletions
README.md
| @@ -6,36 +6,45 @@ | @@ -6,36 +6,45 @@ | ||
| 6 | 6 | ||
| 7 | * 前端采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)。 | 7 | * 前端采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)。 |
| 8 | * 后端采用 Spring Boot、MySQL、Redis。 | 8 | * 后端采用 Spring Boot、MySQL、Redis。 |
| 9 | -* 权限认证使用 Spring Security & JWT,支持多终端认证系统。 | 9 | +* 权限认证使用 Spring Security & Token,支持多终端认证系统。 |
| 10 | * 支持加载动态权限菜单,多方式轻松权限控制。 | 10 | * 支持加载动态权限菜单,多方式轻松权限控制。 |
| 11 | * 高效率开发,使用代码生成器可以一键生成前后端代码。 | 11 | * 高效率开发,使用代码生成器可以一键生成前后端代码。 |
| 12 | 12 | ||
| 13 | ## 内置功能 | 13 | ## 内置功能 |
| 14 | 14 | ||
| 15 | -分成 **业务** 和 **技术** 两类内置功能。 | ||
| 16 | - | ||
| 17 | -### 业务功能 | ||
| 18 | - | ||
| 19 | -1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 | ||
| 20 | -2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 | ||
| 21 | -3. 岗位管理:配置系统用户所属担任职务。 | ||
| 22 | -4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 | ||
| 23 | -5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 | ||
| 24 | -6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 | ||
| 25 | -7. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 | ||
| 26 | -8. 登录日志:系统登录日志记录查询包含登录异常。 | ||
| 27 | -9. 在线用户:当前系统中活跃用户状态监控。 | ||
| 28 | -10. 通知公告:系统通知公告信息发布维护。 | ||
| 29 | - | ||
| 30 | -## 技术功能 | ||
| 31 | - | ||
| 32 | -1. 配置管理:对系统动态配置常用参数。 | ||
| 33 | -2. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 | ||
| 34 | -3. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 | ||
| 35 | -4. 系统接口:根据业务代码自动生成相关的api接口文档。 | ||
| 36 | -5. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 | ||
| 37 | -6. 在线构建器:拖动表单元素生成相应的HTML代码。 | ||
| 38 | -7. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 | 15 | +分成三种内置功能: |
| 16 | +* 系统功能 | ||
| 17 | +* 基础设施 | ||
| 18 | +* 研发工具 | ||
| 19 | + | ||
| 20 | +### 系统功能 | ||
| 21 | + | ||
| 22 | +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置 | ||
| 23 | +1. 在线用户:当前系统中活跃用户状态监控 | ||
| 24 | +1. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分 | ||
| 25 | +1. 菜单管理:配置系统菜单,操作权限,按钮权限标识等 | ||
| 26 | +1. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | ||
| 27 | +1. 岗位管理:配置系统用户所属担任职务 | ||
| 28 | +1. 字典管理:对系统中经常使用的一些较为固定的数据进行维护 | ||
| 29 | +1. 通知公告:系统通知公告信息发布维护 | ||
| 30 | +1. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询 | ||
| 31 | +1. 登录日志:系统登录日志记录查询包含登录异常 | ||
| 32 | + | ||
| 33 | +### 基础设施 | ||
| 34 | + | ||
| 35 | +1. 配置管理:对系统动态配置常用参数 | ||
| 36 | +1. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志 | ||
| 37 | +1. MySQL 监控:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | ||
| 38 | +1. Redis 监控:监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | ||
| 39 | +1. Java 监控:基于 Spring Boot Admin 实现 Java 应用的监控 | ||
| 40 | +1. 链路追踪:基于 SkyWalking 实现性能监控,特别是链路的追踪 | ||
| 41 | + | ||
| 42 | +### 研发工具 | ||
| 43 | + | ||
| 44 | +1. 表单构建:拖动表单元素生成相应的 HTML 代码 | ||
| 45 | +1. 代码生成:前后端代码的生成(Java、Vue、SQL),支持 CRUD 下载 | ||
| 46 | +1. 系统接口:基于 Swagger 自动生成相关的 RESTful API 接口文档 | ||
| 47 | +1. 数据库文档:基于 Screw 自动生成数据库文档 | ||
| 39 | 48 | ||
| 40 | ## 在线体验 | 49 | ## 在线体验 |
| 41 | 50 |
ruoyi-common/src/main/java/com/ruoyi/common/config/FilterConfig.java deleted
| 1 | -package com.ruoyi.framework.config; | ||
| 2 | - | ||
| 3 | -import java.util.HashMap; | ||
| 4 | -import java.util.Map; | ||
| 5 | -import javax.servlet.DispatcherType; | ||
| 6 | - | ||
| 7 | -import org.springframework.beans.factory.annotation.Value; | ||
| 8 | -import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
| 9 | -import org.springframework.context.annotation.Bean; | ||
| 10 | -import org.springframework.context.annotation.Configuration; | ||
| 11 | -import com.ruoyi.common.filter.RepeatableFilter; | ||
| 12 | -import com.ruoyi.common.filter.XssFilter; | ||
| 13 | -import com.ruoyi.common.utils.StringUtils; | ||
| 14 | - | ||
| 15 | -/** | ||
| 16 | - * Filter配置 | ||
| 17 | - * | ||
| 18 | - * @author ruoyi | ||
| 19 | - */ | ||
| 20 | -@Configuration | ||
| 21 | -public class FilterConfig { | ||
| 22 | - @Value("${xss.enabled}") | ||
| 23 | - private String enabled; | ||
| 24 | - | ||
| 25 | - @Value("${xss.excludes}") | ||
| 26 | - private String excludes; | ||
| 27 | - | ||
| 28 | - @Value("${xss.urlPatterns}") | ||
| 29 | - private String urlPatterns; | ||
| 30 | - | ||
| 31 | - @SuppressWarnings({"rawtypes", "unchecked"}) | ||
| 32 | - @Bean | ||
| 33 | - public FilterRegistrationBean xssFilterRegistration() { | ||
| 34 | - FilterRegistrationBean registration = new FilterRegistrationBean(); | ||
| 35 | - registration.setDispatcherTypes(DispatcherType.REQUEST); | ||
| 36 | - registration.setFilter(new XssFilter()); | ||
| 37 | - registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); | ||
| 38 | - registration.setName("xssFilter"); | ||
| 39 | - registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); | ||
| 40 | - Map<String, String> initParameters = new HashMap<String, String>(); | ||
| 41 | - initParameters.put("excludes", excludes); | ||
| 42 | - initParameters.put("enabled", enabled); | ||
| 43 | - registration.setInitParameters(initParameters); | ||
| 44 | - return registration; | ||
| 45 | - } | ||
| 46 | - | ||
| 47 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java deleted
| 1 | -package com.ruoyi.common.filter; | ||
| 2 | - | ||
| 3 | -import java.io.IOException; | ||
| 4 | -import java.util.ArrayList; | ||
| 5 | -import java.util.List; | ||
| 6 | -import java.util.regex.Matcher; | ||
| 7 | -import java.util.regex.Pattern; | ||
| 8 | -import javax.servlet.Filter; | ||
| 9 | -import javax.servlet.FilterChain; | ||
| 10 | -import javax.servlet.FilterConfig; | ||
| 11 | -import javax.servlet.ServletException; | ||
| 12 | -import javax.servlet.ServletRequest; | ||
| 13 | -import javax.servlet.ServletResponse; | ||
| 14 | -import javax.servlet.http.HttpServletRequest; | ||
| 15 | -import javax.servlet.http.HttpServletResponse; | ||
| 16 | -import com.ruoyi.common.utils.StringUtils; | ||
| 17 | - | ||
| 18 | -/** | ||
| 19 | - * 防止XSS攻击的过滤器 | ||
| 20 | - * | ||
| 21 | - * @author ruoyi | ||
| 22 | - */ | ||
| 23 | -public class XssFilter implements Filter | ||
| 24 | -{ | ||
| 25 | - /** | ||
| 26 | - * 排除链接 | ||
| 27 | - */ | ||
| 28 | - public List<String> excludes = new ArrayList<>(); | ||
| 29 | - | ||
| 30 | - /** | ||
| 31 | - * xss过滤开关 | ||
| 32 | - */ | ||
| 33 | - public boolean enabled = false; | ||
| 34 | - | ||
| 35 | - @Override | ||
| 36 | - public void init(FilterConfig filterConfig) throws ServletException | ||
| 37 | - { | ||
| 38 | - String tempExcludes = filterConfig.getInitParameter("excludes"); | ||
| 39 | - String tempEnabled = filterConfig.getInitParameter("enabled"); | ||
| 40 | - if (StringUtils.isNotEmpty(tempExcludes)) | ||
| 41 | - { | ||
| 42 | - String[] url = tempExcludes.split(","); | ||
| 43 | - for (int i = 0; url != null && i < url.length; i++) | ||
| 44 | - { | ||
| 45 | - excludes.add(url[i]); | ||
| 46 | - } | ||
| 47 | - } | ||
| 48 | - if (StringUtils.isNotEmpty(tempEnabled)) | ||
| 49 | - { | ||
| 50 | - enabled = Boolean.valueOf(tempEnabled); | ||
| 51 | - } | ||
| 52 | - } | ||
| 53 | - | ||
| 54 | - @Override | ||
| 55 | - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||
| 56 | - throws IOException, ServletException | ||
| 57 | - { | ||
| 58 | - HttpServletRequest req = (HttpServletRequest) request; | ||
| 59 | - HttpServletResponse resp = (HttpServletResponse) response; | ||
| 60 | - if (handleExcludeURL(req, resp)) | ||
| 61 | - { | ||
| 62 | - chain.doFilter(request, response); | ||
| 63 | - return; | ||
| 64 | - } | ||
| 65 | - XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); | ||
| 66 | - chain.doFilter(xssRequest, response); | ||
| 67 | - } | ||
| 68 | - | ||
| 69 | - private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) | ||
| 70 | - { | ||
| 71 | - if (!enabled) | ||
| 72 | - { | ||
| 73 | - return true; | ||
| 74 | - } | ||
| 75 | - if (excludes == null || excludes.isEmpty()) | ||
| 76 | - { | ||
| 77 | - return false; | ||
| 78 | - } | ||
| 79 | - String url = request.getServletPath(); | ||
| 80 | - for (String pattern : excludes) | ||
| 81 | - { | ||
| 82 | - Pattern p = Pattern.compile("^" + pattern); | ||
| 83 | - Matcher m = p.matcher(url); | ||
| 84 | - if (m.find()) | ||
| 85 | - { | ||
| 86 | - return true; | ||
| 87 | - } | ||
| 88 | - } | ||
| 89 | - return false; | ||
| 90 | - } | ||
| 91 | - | ||
| 92 | - @Override | ||
| 93 | - public void destroy() | ||
| 94 | - { | ||
| 95 | - | ||
| 96 | - } | ||
| 97 | -} | ||
| 98 | \ No newline at end of file | 0 | \ No newline at end of file |
ruoyi-common/src/main/resources/application.yml
| @@ -33,12 +33,3 @@ logging: | @@ -33,12 +33,3 @@ logging: | ||
| 33 | level: | 33 | level: |
| 34 | com.ruoyi: debug | 34 | com.ruoyi: debug |
| 35 | org.springframework: warn | 35 | org.springframework: warn |
| 36 | - | ||
| 37 | -# 防止XSS攻击 | ||
| 38 | -xss: | ||
| 39 | - # 过滤开关 | ||
| 40 | - enabled: true | ||
| 41 | - # 排除链接(多个用逗号分隔) | ||
| 42 | - excludes: /system/notice/* | ||
| 43 | - # 匹配链接 | ||
| 44 | - urlPatterns: /system/*,/monitor/*,/tool/* |
src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java
| 1 | package cn.iocoder.dashboard.framework.web.core.filter; | 1 | package cn.iocoder.dashboard.framework.web.core.filter; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.hutool.core.io.IoUtil; | 4 | import cn.hutool.core.io.IoUtil; |
| 5 | +import cn.hutool.core.util.ArrayUtil; | ||
| 4 | import cn.hutool.core.util.ReflectUtil; | 6 | import cn.hutool.core.util.ReflectUtil; |
| 5 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.hutool.http.HTMLFilter; | 8 | import cn.hutool.http.HTMLFilter; |
| @@ -14,6 +16,7 @@ import java.io.BufferedReader; | @@ -14,6 +16,7 @@ import java.io.BufferedReader; | ||
| 14 | import java.io.ByteArrayInputStream; | 16 | import java.io.ByteArrayInputStream; |
| 15 | import java.io.IOException; | 17 | import java.io.IOException; |
| 16 | import java.io.InputStreamReader; | 18 | import java.io.InputStreamReader; |
| 19 | +import java.util.Map; | ||
| 17 | 20 | ||
| 18 | /** | 21 | /** |
| 19 | * Xss 请求 Wrapper | 22 | * Xss 请求 Wrapper |
| @@ -36,7 +39,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { | @@ -36,7 +39,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { | ||
| 36 | super(request); | 39 | super(request); |
| 37 | } | 40 | } |
| 38 | 41 | ||
| 39 | - private static String filterHtml(String content) { | 42 | + private static String filterXss(String content) { |
| 40 | if (StrUtil.isEmpty(content)) { | 43 | if (StrUtil.isEmpty(content)) { |
| 41 | return content; | 44 | return content; |
| 42 | } | 45 | } |
| @@ -59,7 +62,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { | @@ -59,7 +62,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { | ||
| 59 | 62 | ||
| 60 | // 读取内容,并过滤 | 63 | // 读取内容,并过滤 |
| 61 | String content = IoUtil.readUtf8(super.getInputStream()); | 64 | String content = IoUtil.readUtf8(super.getInputStream()); |
| 62 | - content = filterHtml(content); | 65 | + content = filterXss(content); |
| 63 | final ByteArrayInputStream newInputStream = new ByteArrayInputStream(content.getBytes()); | 66 | final ByteArrayInputStream newInputStream = new ByteArrayInputStream(content.getBytes()); |
| 64 | // 返回 ServletInputStream | 67 | // 返回 ServletInputStream |
| 65 | return new ServletInputStream() { | 68 | return new ServletInputStream() { |
| @@ -87,6 +90,47 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { | @@ -87,6 +90,47 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { | ||
| 87 | 90 | ||
| 88 | // ========== Param 相关 ========== | 91 | // ========== Param 相关 ========== |
| 89 | 92 | ||
| 93 | + @Override | ||
| 94 | + public String getParameter(String name) { | ||
| 95 | + String value = super.getParameter(name); | ||
| 96 | + return filterXss(value); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + @Override | ||
| 100 | + public String[] getParameterValues(String name) { | ||
| 101 | + String[] values = super.getParameterValues(name); | ||
| 102 | + if (ArrayUtil.isEmpty(values)) { | ||
| 103 | + return values; | ||
| 104 | + } | ||
| 105 | + // 过滤处理 | ||
| 106 | + for (int i = 0; i < values.length; i++) { | ||
| 107 | + values[i] = filterXss(values[i]); | ||
| 108 | + } | ||
| 109 | + return values; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + @Override | ||
| 113 | + public Map<String, String[]> getParameterMap() { | ||
| 114 | + Map<String, String[]> valueMap = super.getParameterMap(); | ||
| 115 | + if (CollUtil.isEmpty(valueMap)) { | ||
| 116 | + return valueMap; | ||
| 117 | + } | ||
| 118 | + // 过滤处理 | ||
| 119 | + for (Map.Entry<String, String[]> entry : valueMap.entrySet()) { | ||
| 120 | + String[] values = entry.getValue(); | ||
| 121 | + for (int i = 0; i < values.length; i++) { | ||
| 122 | + values[i] = filterXss(values[i]); | ||
| 123 | + } | ||
| 124 | + } | ||
| 125 | + return valueMap; | ||
| 126 | + } | ||
| 127 | + | ||
| 90 | // ========== Header 相关 ========== | 128 | // ========== Header 相关 ========== |
| 91 | 129 | ||
| 130 | + @Override | ||
| 131 | + public String getHeader(String name) { | ||
| 132 | + String value = super.getHeader(name); | ||
| 133 | + return filterXss(value); | ||
| 134 | + } | ||
| 135 | + | ||
| 92 | } | 136 | } |
src/main/resources/application-dev.yaml
| @@ -87,6 +87,7 @@ apollo: | @@ -87,6 +87,7 @@ apollo: | ||
| 87 | management: | 87 | management: |
| 88 | endpoints: | 88 | endpoints: |
| 89 | web: | 89 | web: |
| 90 | + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator | ||
| 90 | exposure: | 91 | exposure: |
| 91 | include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 | 92 | include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 |
| 92 | 93 | ||
| @@ -131,3 +132,8 @@ yudao: | @@ -131,3 +132,8 @@ yudao: | ||
| 131 | codegen: | 132 | codegen: |
| 132 | base-package: ${yudao.info.base-package}.modules | 133 | base-package: ${yudao.info.base-package}.modules |
| 133 | db-schemas: ${spring.datasource.name} | 134 | db-schemas: ${spring.datasource.name} |
| 135 | + xss: | ||
| 136 | + enable: true | ||
| 137 | + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 | ||
| 138 | + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 | ||
| 139 | + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 |
src/main/resources/application-local.yaml
| @@ -87,6 +87,7 @@ apollo: | @@ -87,6 +87,7 @@ apollo: | ||
| 87 | management: | 87 | management: |
| 88 | endpoints: | 88 | endpoints: |
| 89 | web: | 89 | web: |
| 90 | + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator | ||
| 90 | exposure: | 91 | exposure: |
| 91 | include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 | 92 | include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 |
| 92 | 93 | ||
| @@ -131,3 +132,8 @@ yudao: | @@ -131,3 +132,8 @@ yudao: | ||
| 131 | codegen: | 132 | codegen: |
| 132 | base-package: ${yudao.info.base-package}.modules | 133 | base-package: ${yudao.info.base-package}.modules |
| 133 | db-schemas: ${spring.datasource.name} | 134 | db-schemas: ${spring.datasource.name} |
| 135 | + xss: | ||
| 136 | + enable: true | ||
| 137 | + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 | ||
| 138 | + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 | ||
| 139 | + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 |