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 | 6 | |
| 7 | 7 | * 前端采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)。 |
| 8 | 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 | 0 | \ No newline at end of file |
ruoyi-common/src/main/resources/application.yml
src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java
| 1 | 1 | package cn.iocoder.dashboard.framework.web.core.filter; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.hutool.core.io.IoUtil; |
| 5 | +import cn.hutool.core.util.ArrayUtil; | |
| 4 | 6 | import cn.hutool.core.util.ReflectUtil; |
| 5 | 7 | import cn.hutool.core.util.StrUtil; |
| 6 | 8 | import cn.hutool.http.HTMLFilter; |
| ... | ... | @@ -14,6 +16,7 @@ import java.io.BufferedReader; |
| 14 | 16 | import java.io.ByteArrayInputStream; |
| 15 | 17 | import java.io.IOException; |
| 16 | 18 | import java.io.InputStreamReader; |
| 19 | +import java.util.Map; | |
| 17 | 20 | |
| 18 | 21 | /** |
| 19 | 22 | * Xss 请求 Wrapper |
| ... | ... | @@ -36,7 +39,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { |
| 36 | 39 | super(request); |
| 37 | 40 | } |
| 38 | 41 | |
| 39 | - private static String filterHtml(String content) { | |
| 42 | + private static String filterXss(String content) { | |
| 40 | 43 | if (StrUtil.isEmpty(content)) { |
| 41 | 44 | return content; |
| 42 | 45 | } |
| ... | ... | @@ -59,7 +62,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { |
| 59 | 62 | |
| 60 | 63 | // 读取内容,并过滤 |
| 61 | 64 | String content = IoUtil.readUtf8(super.getInputStream()); |
| 62 | - content = filterHtml(content); | |
| 65 | + content = filterXss(content); | |
| 63 | 66 | final ByteArrayInputStream newInputStream = new ByteArrayInputStream(content.getBytes()); |
| 64 | 67 | // 返回 ServletInputStream |
| 65 | 68 | return new ServletInputStream() { |
| ... | ... | @@ -87,6 +90,47 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { |
| 87 | 90 | |
| 88 | 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 | 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 | 87 | management: |
| 88 | 88 | endpoints: |
| 89 | 89 | web: |
| 90 | + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator | |
| 90 | 91 | exposure: |
| 91 | 92 | include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 |
| 92 | 93 | |
| ... | ... | @@ -131,3 +132,8 @@ yudao: |
| 131 | 132 | codegen: |
| 132 | 133 | base-package: ${yudao.info.base-package}.modules |
| 133 | 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 | 87 | management: |
| 88 | 88 | endpoints: |
| 89 | 89 | web: |
| 90 | + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator | |
| 90 | 91 | exposure: |
| 91 | 92 | include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 |
| 92 | 93 | |
| ... | ... | @@ -131,3 +132,8 @@ yudao: |
| 131 | 132 | codegen: |
| 132 | 133 | base-package: ${yudao.info.base-package}.modules |
| 133 | 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 的请求 | ... | ... |