From 33c6fdfaa9e12328badaa236416cac91384decd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90li?= <15040126243@163.com> Date: Tue, 18 May 2021 11:50:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=20v2.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 21 +++ ruoyi-ui/package.json | 2 +- ruoyi-ui/src/views/index.vue | 11 +- ruoyi/pom.xml | 7 +- .../com/ruoyi/common/core/page/PagePlus.java | 8 - .../ruoyi/framework/config/FilterConfig.java | 33 ++--- .../ruoyi/framework/config/SwaggerConfig.java | 108 ++++++++++++++ .../framework/config/ThreadPoolConfig.java | 55 +++---- .../config/properties/CaptchaProperties.java | 24 +++ .../config/properties/DruidProperties.java | 64 +++----- .../config/properties/SwaggerProperties.java | 59 ++++++++ .../properties/ThreadPoolProperties.java | 47 ++++++ .../config/properties/TokenProperties.java | 26 ++++ .../config/properties/XssProperties.java | 32 ++++ .../framework/web/service/TokenService.java | 82 ++++------- .../controller/common/CaptchaController.java | 29 ++-- .../ruoyi/web/core/config/SwaggerConfig.java | 137 ------------------ ruoyi/src/main/resources/application.yml | 19 ++- ruoyi/src/main/resources/logback.xml | 8 +- 19 files changed, 446 insertions(+), 326 deletions(-) create mode 100644 .editorconfig create mode 100644 ruoyi/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java create mode 100644 ruoyi/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java create mode 100644 ruoyi/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java create mode 100644 ruoyi/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java create mode 100644 ruoyi/src/main/java/com/ruoyi/framework/config/properties/TokenProperties.java create mode 100644 ruoyi/src/main/java/com/ruoyi/framework/config/properties/XssProperties.java delete mode 100644 ruoyi/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..8cfd37094 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# http://editorconfig.org +root = true + +# 空格替代Tab缩进在各种编辑工具下效果一致 +[*] +indent_style = space +indent_size = 4 +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.java] +indent_style = tab + +[*.{json,yml}] +indent_size = 2 + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 0ac7e1556..458a87529 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,6 +1,6 @@ { "name": "ruoyi-vue-plus", - "version": "2.1.0", + "version": "2.1.1", "description": "RuoYi-Vue-Plus后台管理系统", "author": "LionLi", "license": "MIT", diff --git a/ruoyi-ui/src/views/index.vue b/ruoyi-ui/src/views/index.vue index 9cee59a13..25cfa6641 100644 --- a/ruoyi-ui/src/views/index.vue +++ b/ruoyi-ui/src/views/index.vue @@ -80,9 +80,18 @@ 更新日志 + +
    +
  1. update 配置统一提取为 properties 配置类
  2. +
  3. update 分页工具 删除过期方法
  4. +
  5. update admin 实时监控日志 改为保留一天
  6. +
  7. fix 修复swagger开关无法控制关闭问题
  8. +
  9. fix maven install 异常
  10. +
+
    -
  1. update swagger升级3.0.2
  2. +
  3. update knife4j升级3.0.2
  4. update 增强分页工具兼容性
  5. update 通用Service接口 增加自定义vo转换函数
  6. remove 移除ruoyi自带服务监控(Admin已全部包含)
  7. diff --git a/ruoyi/pom.xml b/ruoyi/pom.xml index 444bc7159..454d80195 100644 --- a/ruoyi/pom.xml +++ b/ruoyi/pom.xml @@ -13,7 +13,7 @@ RuoYi-Vue-Plus后台管理系统 - 2.0.0 + 2.1.1 2.3.10.RELEASE UTF-8 UTF-8 @@ -273,6 +273,11 @@ org.springframework.boot spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-configuration-processor + diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/page/PagePlus.java b/ruoyi/src/main/java/com/ruoyi/common/core/page/PagePlus.java index 889d549f5..2bffe3059 100644 --- a/ruoyi/src/main/java/com/ruoyi/common/core/page/PagePlus.java +++ b/ruoyi/src/main/java/com/ruoyi/common/core/page/PagePlus.java @@ -93,14 +93,6 @@ public class PagePlus implements IPage { this.isSearchCount = isSearchCount; } - public boolean hasPrevious() { - return this.current > 1L; - } - - public boolean hasNext() { - return this.current < this.getPages(); - } - @Override public String countId() { return this.getCountId(); diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java index 4626aa1c0..73f7f936c 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/FilterConfig.java @@ -3,7 +3,8 @@ package com.ruoyi.framework.config; import cn.hutool.core.util.StrUtil; import com.ruoyi.common.filter.RepeatableFilter; import com.ruoyi.common.filter.XssFilter; -import org.springframework.beans.factory.annotation.Value; +import com.ruoyi.framework.config.properties.XssProperties; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -15,41 +16,33 @@ import java.util.Map; /** * Filter配置 * - * @author ruoyi + * @author Lion Li */ @Configuration -public class FilterConfig -{ - @Value("${xss.enabled}") - private String enabled; +public class FilterConfig { - @Value("${xss.excludes}") - private String excludes; + @Autowired + private XssProperties xssProperties; - @Value("${xss.urlPatterns}") - private String urlPatterns; - - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) @Bean - public FilterRegistrationBean xssFilterRegistration() - { + public FilterRegistrationBean xssFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setDispatcherTypes(DispatcherType.REQUEST); registration.setFilter(new XssFilter()); - registration.addUrlPatterns(StrUtil.split(urlPatterns, ",")); + registration.addUrlPatterns(StrUtil.split(xssProperties.getUrlPatterns(), ",")); registration.setName("xssFilter"); registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); Map initParameters = new HashMap(); - initParameters.put("excludes", excludes); - initParameters.put("enabled", enabled); + initParameters.put("excludes", xssProperties.getExcludes()); + initParameters.put("enabled", xssProperties.getEnabled()); registration.setInitParameters(initParameters); return registration; } - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) @Bean - public FilterRegistrationBean someFilterRegistration() - { + public FilterRegistrationBean someFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new RepeatableFilter()); registration.addUrlPatterns("/*"); diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java b/ruoyi/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java new file mode 100644 index 000000000..92e39760f --- /dev/null +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java @@ -0,0 +1,108 @@ +package com.ruoyi.framework.config; + +import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; +import com.ruoyi.framework.config.properties.SwaggerProperties; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.*; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.ArrayList; +import java.util.List; + +/** + * Swagger2的接口配置 + * + * @author Lion Li + */ +@Configuration +@EnableSwagger2 +@EnableKnife4j +public class SwaggerConfig { + + @Autowired + private SwaggerProperties swaggerProperties; + + /** + * 创建API + */ + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .enable(swaggerProperties.getEnabled()) + // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息) + .apiInfo(apiInfo()) + // 设置哪些接口暴露给Swagger展示 + .select() + // 扫描所有有注解的api,用这种方式更灵活 + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + // 扫描指定包中的swagger注解 + // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger")) + // 扫描所有 .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build() + /* 设置安全模式,swagger可以设置访问token */ + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()); + } + + /** + * 安全模式,这里指定token通过Authorization头请求头传递 + */ + private List securitySchemes() { + List apiKeyList = new ArrayList(); + apiKeyList.add(new ApiKey("Authorization", "Authorization", "header")); + return apiKeyList; + } + + /** + * 安全上下文 + */ + private List securityContexts() { + List securityContexts = new ArrayList<>(); + securityContexts.add( + SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex("^(?!auth).*$")) + .build()); + return securityContexts; + } + + /** + * 默认的安全上引用 + */ + private List defaultAuth() { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + List securityReferences = new ArrayList<>(); + securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); + return securityReferences; + } + + /** + * 添加摘要信息 + */ + private ApiInfo apiInfo() { + // 用ApiInfoBuilder进行定制 + SwaggerProperties.Contact contact = swaggerProperties.getContact(); + return new ApiInfoBuilder() + // 设置标题 + .title(swaggerProperties.getTitle()) + // 描述 + .description(swaggerProperties.getDescription()) + // 作者信息 + .contact(new Contact(contact.getName(), contact.getUrl(), contact.getEmail())) + // 版本 + .version(swaggerProperties.getVersion()) + .build(); + } +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/ruoyi/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java index 30d5ef91f..104838327 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java @@ -1,8 +1,9 @@ package com.ruoyi.framework.config; import com.ruoyi.common.utils.Threads; +import com.ruoyi.framework.config.properties.ThreadPoolProperties; import org.apache.commons.lang3.concurrent.BasicThreadFactory; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,43 +22,31 @@ import java.util.concurrent.ThreadPoolExecutor; @Configuration public class ThreadPoolConfig { - // 核心线程池大小 - @Value("${threadPoolConfig.corePoolSize}") - private int corePoolSize; - - // 最大可创建的线程数 - @Value("${threadPoolConfig.maxPoolSize}") - private int maxPoolSize; - - // 队列最大长度 - @Value("${threadPoolConfig.queueCapacity}") - private int queueCapacity; - - // 线程池维护线程所允许的空闲时间 - @Value("${threadPoolConfig.keepAliveSeconds}") - private int keepAliveSeconds; - - // 线程池对拒绝任务(无线程可用)的处理策略 - @Value("${threadPoolConfig.rejectedExecutionHandler}") - private String rejectedExecutionHandler; + @Autowired + private ThreadPoolProperties threadPoolProperties; @Bean(name = "threadPoolTaskExecutor") @ConditionalOnProperty(prefix = "threadPoolTaskExecutor", name = "enabled", havingValue = "true") public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setMaxPoolSize(maxPoolSize); - executor.setCorePoolSize(corePoolSize); - executor.setQueueCapacity(queueCapacity); - executor.setKeepAliveSeconds(keepAliveSeconds); + executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize()); + executor.setCorePoolSize(threadPoolProperties.getCorePoolSize()); + executor.setQueueCapacity(threadPoolProperties.getQueueCapacity()); + executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds()); RejectedExecutionHandler handler; - if (rejectedExecutionHandler.equals("CallerRunsPolicy")) { - handler = new ThreadPoolExecutor.CallerRunsPolicy(); - } else if (rejectedExecutionHandler.equals("DiscardOldestPolicy")) { - handler = new ThreadPoolExecutor.DiscardOldestPolicy(); - } else if (rejectedExecutionHandler.equals("DiscardPolicy")) { - handler = new ThreadPoolExecutor.DiscardPolicy(); - } else { - handler = new ThreadPoolExecutor.AbortPolicy(); + switch (threadPoolProperties.getRejectedExecutionHandler()) { + case "CallerRunsPolicy": + handler = new ThreadPoolExecutor.CallerRunsPolicy(); + break; + case "DiscardOldestPolicy": + handler = new ThreadPoolExecutor.DiscardOldestPolicy(); + break; + case "DiscardPolicy": + handler = new ThreadPoolExecutor.DiscardPolicy(); + break; + default: + handler = new ThreadPoolExecutor.AbortPolicy(); + break; } executor.setRejectedExecutionHandler(handler); return executor; @@ -68,7 +57,7 @@ public class ThreadPoolConfig { */ @Bean(name = "scheduledExecutorService") protected ScheduledExecutorService scheduledExecutorService() { - return new ScheduledThreadPoolExecutor(corePoolSize, + return new ScheduledThreadPoolExecutor(threadPoolProperties.getCorePoolSize(), new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) { @Override protected void afterExecute(Runnable r, Throwable t) { diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java new file mode 100644 index 000000000..24356bca6 --- /dev/null +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java @@ -0,0 +1,24 @@ +package com.ruoyi.framework.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 验证码 配置属性 + * + * @author Lion Li + */ +@Data +@Component +@ConfigurationProperties(prefix = "captcha") +public class CaptchaProperties { + // 验证码类型 + private String type; + // 验证码类别 + private String category; + // 数字验证码位数 + private Integer numberLength; + // 字符验证码长度 + private Integer charLength; +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java index 84f7e0090..03ddc2c5a 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java @@ -1,76 +1,54 @@ package com.ruoyi.framework.config.properties; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; import com.alibaba.druid.pool.DruidDataSource; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; /** * druid 配置属性 - * - * @author ruoyi + * + * @author Lion Li */ +@Data @Configuration -public class DruidProperties -{ - @Value("${spring.datasource.druid.initialSize}") +@ConfigurationProperties(prefix = "spring.datasource.druid") +public class DruidProperties { + + /** 初始连接数 */ private int initialSize; - - @Value("${spring.datasource.druid.minIdle}") + /** 最小连接池数量 */ private int minIdle; - - @Value("${spring.datasource.druid.maxActive}") + /** 最大连接池数量 */ private int maxActive; - - @Value("${spring.datasource.druid.maxWait}") + /** 配置获取连接等待超时的时间 */ private int maxWait; - - @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}") + /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */ private int timeBetweenEvictionRunsMillis; - - @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}") + /** 配置一个连接在池中最小生存的时间,单位是毫秒 */ private int minEvictableIdleTimeMillis; - - @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}") + /** 配置一个连接在池中最大生存的时间,单位是毫秒 */ private int maxEvictableIdleTimeMillis; - - @Value("${spring.datasource.druid.validationQuery}") + /** 配置检测连接是否有效 */ private String validationQuery; - - @Value("${spring.datasource.druid.testWhileIdle}") + /** 初始连接数 */ private boolean testWhileIdle; - - @Value("${spring.datasource.druid.testOnBorrow}") + /** 初始连接数 */ private boolean testOnBorrow; - - @Value("${spring.datasource.druid.testOnReturn}") + /** 初始连接数 */ private boolean testOnReturn; - public DruidDataSource dataSource(DruidDataSource datasource) - { - /** 配置初始化大小、最小、最大 */ + public DruidDataSource dataSource(DruidDataSource datasource) { datasource.setInitialSize(initialSize); datasource.setMaxActive(maxActive); datasource.setMinIdle(minIdle); - - /** 配置获取连接等待超时的时间 */ datasource.setMaxWait(maxWait); - - /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */ datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); - - /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */ datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis); - - /** - * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 - */ datasource.setValidationQuery(validationQuery); - /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */ datasource.setTestWhileIdle(testWhileIdle); - /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ datasource.setTestOnBorrow(testOnBorrow); - /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ datasource.setTestOnReturn(testOnReturn); return datasource; } diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java new file mode 100644 index 000000000..4db6e5884 --- /dev/null +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java @@ -0,0 +1,59 @@ +package com.ruoyi.framework.config.properties; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 验证码 配置属性 + * + * @author Lion Li + */ +@Data +@Component +@ConfigurationProperties(prefix = "swagger") +public class SwaggerProperties { + + /** + * 验证码类型 + */ + private Boolean enabled; + /** + * 验证码类别 + */ + private String title; + /** + * 数字验证码位数 + */ + private String description; + /** + * 字符验证码长度 + */ + private String version; + + /** + * 联系方式 + */ + private Contact contact; + + @Data + @NoArgsConstructor + public static class Contact{ + + /** + * 联系人 + **/ + private String name; + /** + * 联系人url + **/ + private String url; + /** + * 联系人email + **/ + private String email; + + } + +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java new file mode 100644 index 000000000..68cb09337 --- /dev/null +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java @@ -0,0 +1,47 @@ +package com.ruoyi.framework.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 验证码 配置属性 + * + * @author Lion Li + */ +@Data +@Component +@ConfigurationProperties(prefix = "thread-pool") +public class ThreadPoolProperties { + + /** + * 是否开启线程池 + */ + private boolean enabled; + + /** + * 核心线程池大小 + */ + private int corePoolSize; + + /** + * 最大可创建的线程数 + */ + private int maxPoolSize; + + /** + * 队列最大长度 + */ + private int queueCapacity; + + /** + * 线程池维护线程所允许的空闲时间 + */ + private int keepAliveSeconds; + + /** + * 线程池对拒绝任务(无线程可用)的处理策略 + */ + private String rejectedExecutionHandler; + +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/TokenProperties.java b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/TokenProperties.java new file mode 100644 index 000000000..d582e5407 --- /dev/null +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/TokenProperties.java @@ -0,0 +1,26 @@ +package com.ruoyi.framework.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "token") +public class TokenProperties { + + /** + * 令牌自定义标识 + */ + private String header; + + /** + * 令牌秘钥 + */ + private String secret; + + /** + * 令牌有效期(默认30分钟) + */ + private int expireTime; +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/properties/XssProperties.java b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/XssProperties.java new file mode 100644 index 000000000..35ae2e4ff --- /dev/null +++ b/ruoyi/src/main/java/com/ruoyi/framework/config/properties/XssProperties.java @@ -0,0 +1,32 @@ +package com.ruoyi.framework.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 验证码 配置属性 + * + * @author Lion Li + */ +@Data +@Component +@ConfigurationProperties(prefix = "xss") +public class XssProperties { + + /** + * 过滤开关 + */ + private String enabled; + + /** + * 排除链接(多个用逗号分隔) + */ + private String excludes; + + /** + * 匹配链接 + */ + private String urlPatterns; + +} diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi/src/main/java/com/ruoyi/framework/web/service/TokenService.java index c55078dee..0db777bcc 100644 --- a/ruoyi/src/main/java/com/ruoyi/framework/web/service/TokenService.java +++ b/ruoyi/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -10,11 +10,11 @@ import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.framework.config.properties.TokenProperties; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @@ -25,22 +25,10 @@ import java.util.concurrent.TimeUnit; /** * token验证处理 * - * @author ruoyi + * @author Lion Li */ @Component -public class TokenService -{ - // 令牌自定义标识 - @Value("${token.header}") - private String header; - - // 令牌秘钥 - @Value("${token.secret}") - private String secret; - - // 令牌有效期(默认30分钟) - @Value("${token.expireTime}") - private int expireTime; +public class TokenService { protected static final long MILLIS_SECOND = 1000; @@ -51,17 +39,18 @@ public class TokenService @Autowired private RedisCache redisCache; + @Autowired + private TokenProperties tokenProperties; + /** * 获取用户身份信息 * * @return 用户信息 */ - public LoginUser getLoginUser(HttpServletRequest request) - { + public LoginUser getLoginUser(HttpServletRequest request) { // 获取请求携带的令牌 String token = getToken(request); - if (Validator.isNotEmpty(token)) - { + if (Validator.isNotEmpty(token)) { Claims claims = parseToken(token); // 解析对应的权限以及用户信息 String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); @@ -75,10 +64,8 @@ public class TokenService /** * 设置用户身份信息 */ - public void setLoginUser(LoginUser loginUser) - { - if (Validator.isNotNull(loginUser) && Validator.isNotEmpty(loginUser.getToken())) - { + public void setLoginUser(LoginUser loginUser) { + if (Validator.isNotNull(loginUser) && Validator.isNotEmpty(loginUser.getToken())) { refreshToken(loginUser); } } @@ -86,10 +73,8 @@ public class TokenService /** * 删除用户身份信息 */ - public void delLoginUser(String token) - { - if (Validator.isNotEmpty(token)) - { + public void delLoginUser(String token) { + if (Validator.isNotEmpty(token)) { String userKey = getTokenKey(token); redisCache.deleteObject(userKey); } @@ -101,8 +86,7 @@ public class TokenService * @param loginUser 用户信息 * @return 令牌 */ - public String createToken(LoginUser loginUser) - { + public String createToken(LoginUser loginUser) { String token = IdUtil.fastUUID(); loginUser.setToken(token); setUserAgent(loginUser); @@ -119,12 +103,10 @@ public class TokenService * @param loginUser * @return 令牌 */ - public void verifyToken(LoginUser loginUser) - { + public void verifyToken(LoginUser loginUser) { long expireTime = loginUser.getExpireTime(); long currentTime = System.currentTimeMillis(); - if (expireTime - currentTime <= MILLIS_MINUTE_TEN) - { + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { refreshToken(loginUser); } } @@ -134,13 +116,12 @@ public class TokenService * * @param loginUser 登录信息 */ - public void refreshToken(LoginUser loginUser) - { + public void refreshToken(LoginUser loginUser) { loginUser.setLoginTime(System.currentTimeMillis()); - loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); + loginUser.setExpireTime(loginUser.getLoginTime() + tokenProperties.getExpireTime() * MILLIS_MINUTE); // 根据uuid将loginUser缓存 String userKey = getTokenKey(loginUser.getToken()); - redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + redisCache.setCacheObject(userKey, loginUser, tokenProperties.getExpireTime(), TimeUnit.MINUTES); } /** @@ -148,8 +129,7 @@ public class TokenService * * @param loginUser 登录信息 */ - public void setUserAgent(LoginUser loginUser) - { + public void setUserAgent(LoginUser loginUser) { UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); loginUser.setIpaddr(ip); @@ -164,11 +144,10 @@ public class TokenService * @param claims 数据声明 * @return 令牌 */ - private String createToken(Map claims) - { + private String createToken(Map claims) { String token = Jwts.builder() .setClaims(claims) - .signWith(SignatureAlgorithm.HS512, secret).compact(); + .signWith(SignatureAlgorithm.HS512, tokenProperties.getSecret()).compact(); return token; } @@ -178,10 +157,9 @@ public class TokenService * @param token 令牌 * @return 数据声明 */ - private Claims parseToken(String token) - { + private Claims parseToken(String token) { return Jwts.parser() - .setSigningKey(secret) + .setSigningKey(tokenProperties.getSecret()) .parseClaimsJws(token) .getBody(); } @@ -192,8 +170,7 @@ public class TokenService * @param token 令牌 * @return 用户名 */ - public String getUsernameFromToken(String token) - { + public String getUsernameFromToken(String token) { Claims claims = parseToken(token); return claims.getSubject(); } @@ -204,18 +181,15 @@ public class TokenService * @param request * @return token */ - private String getToken(HttpServletRequest request) - { - String token = request.getHeader(header); - if (Validator.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) - { + private String getToken(HttpServletRequest request) { + String token = request.getHeader(tokenProperties.getHeader()); + if (Validator.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { token = token.replace(Constants.TOKEN_PREFIX, ""); } return token; } - private String getTokenKey(String uuid) - { + private String getTokenKey(String uuid) { return Constants.LOGIN_TOKEN_KEY + uuid; } } diff --git a/ruoyi/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java index 48e4e4ecd..c01cc4ed7 100644 --- a/ruoyi/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java +++ b/ruoyi/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -13,8 +13,8 @@ import cn.hutool.core.util.StrUtil; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.framework.config.properties.CaptchaProperties; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -42,18 +42,8 @@ public class CaptchaController { @Autowired private RedisCache redisCache; - // 验证码类型 - @Value("${captcha.captchaType}") - private String captchaType; - // 验证码类别 - @Value("${captcha.captchaCategory}") - private String captchaCategory; - // 数字验证码位数 - @Value("${captcha.captchaNumberLength}") - private int numberLength; - // 字符验证码长度 - @Value("${captcha.captchaCharLength}") - private int charLength; + @Autowired + private CaptchaProperties captchaProperties; /** * 生成验证码 @@ -67,17 +57,17 @@ public class CaptchaController { // 生成验证码 CodeGenerator codeGenerator; AbstractCaptcha captcha; - switch (captchaType) { + switch (captchaProperties.getType()) { case "math": - codeGenerator = new MathGenerator(numberLength); + codeGenerator = new MathGenerator(captchaProperties.getNumberLength()); break; case "char": - codeGenerator = new RandomGenerator(charLength); + codeGenerator = new RandomGenerator(captchaProperties.getCharLength()); break; default: throw new IllegalArgumentException("验证码类型异常"); } - switch (captchaCategory) { + switch (captchaProperties.getCategory()) { case "line": captcha = lineCaptcha; break; @@ -92,9 +82,9 @@ public class CaptchaController { } captcha.setGenerator(codeGenerator); captcha.createCode(); - if ("math".equals(captchaType)) { + if ("math".equals(captchaProperties.getType())) { code = getCodeResult(captcha.getCode()); - } else if ("char".equals(captchaType)) { + } else if ("char".equals(captchaProperties.getType())) { code = captcha.getCode(); } redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); @@ -105,6 +95,7 @@ public class CaptchaController { } private String getCodeResult(String capStr) { + int numberLength = captchaProperties.getNumberLength(); int a = Convert.toInt(StrUtil.sub(capStr, 0, numberLength).trim()); char operator = capStr.charAt(numberLength); int b = Convert.toInt(StrUtil.sub(capStr, numberLength + 1, numberLength + 1 + numberLength).trim()); diff --git a/ruoyi/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java deleted file mode 100644 index 39c7786ea..000000000 --- a/ruoyi/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.ruoyi.web.core.config; - -import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; -import com.ruoyi.common.config.RuoYiConfig; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.*; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -import java.util.ArrayList; -import java.util.List; - -/** - * Swagger2的接口配置 - * - * @author Lion Li - */ -@Configuration -@EnableSwagger2 -@EnableKnife4j -@ConditionalOnClass({Docket.class, ApiInfoBuilder.class}) -@ConditionalOnProperty(prefix = "swagger", value = "enable", matchIfMissing = true) -public class SwaggerConfig { - /** - * 系统基础配置 - */ - @Autowired - private RuoYiConfig ruoyiConfig; - - /** - * 设置请求的统一前缀 - */ - @Value("${swagger.pathMapping}") - private String pathMapping; - - /** - * 标题 - */ - @Value("${swagger.title}") - private String title; - - /** - * 描述 - */ - @Value("${swagger.description}") - private String description; - - /** - * 版本 - */ - @Value("${swagger.version}") - private String version; - - /** - * 创建API - */ - @Bean - public Docket createRestApi() { - return new Docket(DocumentationType.SWAGGER_2) - // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息) - .apiInfo(apiInfo()) - // 设置哪些接口暴露给Swagger展示 - .select() - // 扫描所有有注解的api,用这种方式更灵活 - .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) - // 扫描指定包中的swagger注解 - // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger")) - // 扫描所有 .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) - .build() - /* 设置安全模式,swagger可以设置访问token */ - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()); - } - - /** - * 安全模式,这里指定token通过Authorization头请求头传递 - */ - private List securitySchemes() { - List apiKeyList = new ArrayList(); - apiKeyList.add(new ApiKey("Authorization", "Authorization", "header")); - return apiKeyList; - } - - /** - * 安全上下文 - */ - private List securityContexts() { - List securityContexts = new ArrayList<>(); - securityContexts.add( - SecurityContext.builder() - .securityReferences(defaultAuth()) - .forPaths(PathSelectors.regex("^(?!auth).*$")) - .build()); - return securityContexts; - } - - /** - * 默认的安全上引用 - */ - private List defaultAuth() { - AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - List securityReferences = new ArrayList<>(); - securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); - return securityReferences; - } - - /** - * 添加摘要信息 - */ - private ApiInfo apiInfo() { - // 用ApiInfoBuilder进行定制 - return new ApiInfoBuilder() - // 设置标题 - .title(title) - // 描述 - .description(description) - // 作者信息 - .contact(new Contact(ruoyiConfig.getName(), null, null)) - // 版本 - .version(version) - .build(); - } -} diff --git a/ruoyi/src/main/resources/application.yml b/ruoyi/src/main/resources/application.yml index 4f6d87664..b034d99fc 100644 --- a/ruoyi/src/main/resources/application.yml +++ b/ruoyi/src/main/resources/application.yml @@ -15,13 +15,13 @@ ruoyi: captcha: # 验证码类型 math 数组计算 char 字符验证 - captchaType: math + type: math # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰 - captchaCategory: circle + category: circle # 数字验证码位数 - captchaNumberLength: 1 + numberLength: 1 # 字符验证码长度 - captchaCharLength: 4 + charLength: 4 # 开发环境配置 server: @@ -187,14 +187,17 @@ mybatis-plus: swagger: # 是否开启swagger enabled: true - # 请求前缀 - pathMapping: /dev-api # 标题 title: '标题:RuoYi-Vue-Plus后台管理系统_接口文档' # 描述 description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...' # 版本 version: '版本号: ${ruoyi-vue-plus.version}' + # 作者信息 + contact: + name: Lion Li + email: crazylionli@163.com + url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus # 防止XSS攻击 xss: @@ -206,7 +209,7 @@ xss: urlPatterns: /system/*,/monitor/*,/tool/* # 全局线程池相关配置 -threadPoolConfig: +thread-pool: # 是否开启线程池 enabled: false # 核心线程池大小 @@ -297,4 +300,4 @@ management: include: '*' endpoint: logfile: - external-file: ./logs/sys-console.log \ No newline at end of file + external-file: ./logs/sys-console.log diff --git a/ruoyi/src/main/resources/logback.xml b/ruoyi/src/main/resources/logback.xml index d407df43e..c939785e6 100644 --- a/ruoyi/src/main/resources/logback.xml +++ b/ruoyi/src/main/resources/logback.xml @@ -14,8 +14,14 @@ - + ${log.path}/sys-console.log + + + ${log.path}/sys-console.%d{yyyy-MM-dd}.log + + 1 + ${log.pattern} utf-8