caojianbin
2 years ago
42 changed files with 1357 additions and 1361 deletions
@ -1,29 +1,29 @@
@@ -1,29 +1,29 @@
|
||||
package com.ruoyi.gateway; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; |
||||
|
||||
/** |
||||
* 网关启动程序 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) |
||||
public class RuoYiGatewayApplication |
||||
{ |
||||
public static void main(String[] args) |
||||
{ |
||||
SpringApplication.run(RuoYiGatewayApplication.class, args); |
||||
System.out.println("(♥◠‿◠)ノ゙ 若依网关启动成功 ლ(´ڡ`ლ)゙ \n" + |
||||
" .-------. ____ __ \n" + |
||||
" | _ _ \\ \\ \\ / / \n" + |
||||
" | ( ' ) | \\ _. / ' \n" + |
||||
" |(_ o _) / _( )_ .' \n" + |
||||
" | (_,_).' __ ___(_ o _)' \n" + |
||||
" | |\\ \\ | || |(_,_)' \n" + |
||||
" | | \\ `' /| `-' / \n" + |
||||
" | | \\ / \\ / \n" + |
||||
" ''-' `'-' `-..-' "); |
||||
} |
||||
} |
||||
package com.yisai.gateway; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; |
||||
|
||||
/** |
||||
* 网关启动程序 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) |
||||
public class RuoYiGatewayApplication |
||||
{ |
||||
public static void main(String[] args) |
||||
{ |
||||
SpringApplication.run(RuoYiGatewayApplication.class, args); |
||||
System.out.println("(♥◠‿◠)ノ゙ 若依网关启动成功 ლ(´ڡ`ლ)゙ \n" + |
||||
" .-------. ____ __ \n" + |
||||
" | _ _ \\ \\ \\ / / \n" + |
||||
" | ( ' ) | \\ _. / ' \n" + |
||||
" |(_ o _) / _( )_ .' \n" + |
||||
" | (_,_).' __ ___(_ o _)' \n" + |
||||
" | |\\ \\ | || |(_,_)' \n" + |
||||
" | | \\ `' /| `-' / \n" + |
||||
" | | \\ / \\ / \n" + |
||||
" ''-' `'-' `-..-' "); |
||||
} |
||||
} |
@ -1,83 +1,83 @@
@@ -1,83 +1,83 @@
|
||||
package com.ruoyi.gateway.config; |
||||
|
||||
import java.util.Properties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import com.google.code.kaptcha.impl.DefaultKaptcha; |
||||
import com.google.code.kaptcha.util.Config; |
||||
import static com.google.code.kaptcha.Constants.*; |
||||
|
||||
/** |
||||
* 验证码配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class CaptchaConfig |
||||
{ |
||||
@Bean(name = "captchaProducer") |
||||
public DefaultKaptcha getKaptchaBean() |
||||
{ |
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); |
||||
Properties properties = new Properties(); |
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes"); |
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); |
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); |
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); |
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); |
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); |
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); |
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); |
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); |
||||
Config config = new Config(properties); |
||||
defaultKaptcha.setConfig(config); |
||||
return defaultKaptcha; |
||||
} |
||||
|
||||
@Bean(name = "captchaProducerMath") |
||||
public DefaultKaptcha getKaptchaBeanMath() |
||||
{ |
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); |
||||
Properties properties = new Properties(); |
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes"); |
||||
// 边框颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); |
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); |
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); |
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); |
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); |
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); |
||||
// 验证码文本生成器
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator"); |
||||
// 验证码文本字符间距 默认为2
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); |
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); |
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); |
||||
// 验证码噪点颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); |
||||
// 干扰实现类
|
||||
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); |
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); |
||||
Config config = new Config(properties); |
||||
defaultKaptcha.setConfig(config); |
||||
return defaultKaptcha; |
||||
} |
||||
package com.yisai.gateway.config; |
||||
|
||||
import java.util.Properties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import com.google.code.kaptcha.impl.DefaultKaptcha; |
||||
import com.google.code.kaptcha.util.Config; |
||||
import static com.google.code.kaptcha.Constants.*; |
||||
|
||||
/** |
||||
* 验证码配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class CaptchaConfig |
||||
{ |
||||
@Bean(name = "captchaProducer") |
||||
public DefaultKaptcha getKaptchaBean() |
||||
{ |
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); |
||||
Properties properties = new Properties(); |
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes"); |
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); |
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); |
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); |
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); |
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); |
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); |
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); |
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); |
||||
Config config = new Config(properties); |
||||
defaultKaptcha.setConfig(config); |
||||
return defaultKaptcha; |
||||
} |
||||
|
||||
@Bean(name = "captchaProducerMath") |
||||
public DefaultKaptcha getKaptchaBeanMath() |
||||
{ |
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); |
||||
Properties properties = new Properties(); |
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes"); |
||||
// 边框颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); |
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); |
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); |
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); |
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); |
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); |
||||
// 验证码文本生成器
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator"); |
||||
// 验证码文本字符间距 默认为2
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); |
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); |
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); |
||||
// 验证码噪点颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); |
||||
// 干扰实现类
|
||||
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); |
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); |
||||
Config config = new Config(properties); |
||||
defaultKaptcha.setConfig(config); |
||||
return defaultKaptcha; |
||||
} |
||||
} |
@ -1,23 +1,23 @@
@@ -1,23 +1,23 @@
|
||||
package com.ruoyi.gateway.config; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.core.annotation.Order; |
||||
import com.ruoyi.gateway.handler.SentinelFallbackHandler; |
||||
|
||||
/** |
||||
* 网关限流配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class GatewayConfig |
||||
{ |
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) |
||||
public SentinelFallbackHandler sentinelGatewayExceptionHandler() |
||||
{ |
||||
return new SentinelFallbackHandler(); |
||||
} |
||||
package com.yisai.gateway.config; |
||||
|
||||
import com.yisai.gateway.handler.SentinelFallbackHandler; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.core.annotation.Order; |
||||
|
||||
/** |
||||
* 网关限流配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class GatewayConfig |
||||
{ |
||||
@Bean |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) |
||||
public SentinelFallbackHandler sentinelGatewayExceptionHandler() |
||||
{ |
||||
return new SentinelFallbackHandler(); |
||||
} |
||||
} |
@ -1,75 +1,75 @@
@@ -1,75 +1,75 @@
|
||||
package com.ruoyi.gateway.config; |
||||
|
||||
import java.util.Random; |
||||
import com.google.code.kaptcha.text.impl.DefaultTextCreator; |
||||
|
||||
/** |
||||
* 验证码文本生成器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class KaptchaTextCreator extends DefaultTextCreator |
||||
{ |
||||
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); |
||||
|
||||
@Override |
||||
public String getText() |
||||
{ |
||||
Integer result = 0; |
||||
Random random = new Random(); |
||||
int x = random.nextInt(10); |
||||
int y = random.nextInt(10); |
||||
StringBuilder suChinese = new StringBuilder(); |
||||
int randomoperands = (int) Math.round(Math.random() * 2); |
||||
if (randomoperands == 0) |
||||
{ |
||||
result = x * y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("*"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
else if (randomoperands == 1) |
||||
{ |
||||
if (!(x == 0) && y % x == 0) |
||||
{ |
||||
result = y / x; |
||||
suChinese.append(CNUMBERS[y]); |
||||
suChinese.append("/"); |
||||
suChinese.append(CNUMBERS[x]); |
||||
} |
||||
else |
||||
{ |
||||
result = x + y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("+"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
} |
||||
else if (randomoperands == 2) |
||||
{ |
||||
if (x >= y) |
||||
{ |
||||
result = x - y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("-"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
else |
||||
{ |
||||
result = y - x; |
||||
suChinese.append(CNUMBERS[y]); |
||||
suChinese.append("-"); |
||||
suChinese.append(CNUMBERS[x]); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
result = x + y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("+"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
suChinese.append("=?@" + result); |
||||
return suChinese.toString(); |
||||
} |
||||
package com.yisai.gateway.config; |
||||
|
||||
import java.util.Random; |
||||
import com.google.code.kaptcha.text.impl.DefaultTextCreator; |
||||
|
||||
/** |
||||
* 验证码文本生成器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class KaptchaTextCreator extends DefaultTextCreator |
||||
{ |
||||
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); |
||||
|
||||
@Override |
||||
public String getText() |
||||
{ |
||||
Integer result = 0; |
||||
Random random = new Random(); |
||||
int x = random.nextInt(10); |
||||
int y = random.nextInt(10); |
||||
StringBuilder suChinese = new StringBuilder(); |
||||
int randomoperands = (int) Math.round(Math.random() * 2); |
||||
if (randomoperands == 0) |
||||
{ |
||||
result = x * y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("*"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
else if (randomoperands == 1) |
||||
{ |
||||
if (!(x == 0) && y % x == 0) |
||||
{ |
||||
result = y / x; |
||||
suChinese.append(CNUMBERS[y]); |
||||
suChinese.append("/"); |
||||
suChinese.append(CNUMBERS[x]); |
||||
} |
||||
else |
||||
{ |
||||
result = x + y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("+"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
} |
||||
else if (randomoperands == 2) |
||||
{ |
||||
if (x >= y) |
||||
{ |
||||
result = x - y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("-"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
else |
||||
{ |
||||
result = y - x; |
||||
suChinese.append(CNUMBERS[y]); |
||||
suChinese.append("-"); |
||||
suChinese.append(CNUMBERS[x]); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
result = x + y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("+"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
suChinese.append("=?@" + result); |
||||
return suChinese.toString(); |
||||
} |
||||
} |
@ -1,31 +1,31 @@
@@ -1,31 +1,31 @@
|
||||
package com.ruoyi.gateway.config; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.web.reactive.function.server.RequestPredicates; |
||||
import org.springframework.web.reactive.function.server.RouterFunction; |
||||
import org.springframework.web.reactive.function.server.RouterFunctions; |
||||
import com.ruoyi.gateway.handler.ValidateCodeHandler; |
||||
|
||||
/** |
||||
* 路由配置信息 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class RouterFunctionConfiguration |
||||
{ |
||||
@Autowired |
||||
private ValidateCodeHandler validateCodeHandler; |
||||
|
||||
@SuppressWarnings("rawtypes") |
||||
@Bean |
||||
public RouterFunction routerFunction() |
||||
{ |
||||
return RouterFunctions.route( |
||||
RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), |
||||
validateCodeHandler); |
||||
} |
||||
} |
||||
package com.yisai.gateway.config; |
||||
|
||||
import com.yisai.gateway.handler.ValidateCodeHandler; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.web.reactive.function.server.RequestPredicates; |
||||
import org.springframework.web.reactive.function.server.RouterFunction; |
||||
import org.springframework.web.reactive.function.server.RouterFunctions; |
||||
|
||||
/** |
||||
* 路由配置信息 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class RouterFunctionConfiguration |
||||
{ |
||||
@Autowired |
||||
private ValidateCodeHandler validateCodeHandler; |
||||
|
||||
@SuppressWarnings("rawtypes") |
||||
@Bean |
||||
public RouterFunction routerFunction() |
||||
{ |
||||
return RouterFunctions.route( |
||||
RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), |
||||
validateCodeHandler); |
||||
} |
||||
} |
@ -1,79 +1,79 @@
@@ -1,79 +1,79 @@
|
||||
package com.ruoyi.gateway.config; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.cloud.gateway.config.GatewayProperties; |
||||
import org.springframework.cloud.gateway.route.RouteLocator; |
||||
import org.springframework.cloud.gateway.support.NameUtils; |
||||
import org.springframework.context.annotation.Lazy; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.reactive.config.ResourceHandlerRegistry; |
||||
import org.springframework.web.reactive.config.WebFluxConfigurer; |
||||
import springfox.documentation.swagger.web.SwaggerResource; |
||||
import springfox.documentation.swagger.web.SwaggerResourcesProvider; |
||||
|
||||
/** |
||||
* 聚合系统接口 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class SwaggerProvider implements SwaggerResourcesProvider, WebFluxConfigurer |
||||
{ |
||||
/** |
||||
* Swagger2默认的url后缀 |
||||
*/ |
||||
public static final String SWAGGER2URL = "/v2/api-docs"; |
||||
|
||||
/** |
||||
* 网关路由 |
||||
*/ |
||||
@Lazy |
||||
@Autowired |
||||
private RouteLocator routeLocator; |
||||
|
||||
@Autowired |
||||
private GatewayProperties gatewayProperties; |
||||
|
||||
/** |
||||
* 聚合其他服务接口 |
||||
* |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public List<SwaggerResource> get() |
||||
{ |
||||
List<SwaggerResource> resourceList = new ArrayList<>(); |
||||
List<String> routes = new ArrayList<>(); |
||||
// 获取网关中配置的route
|
||||
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); |
||||
gatewayProperties.getRoutes().stream() |
||||
.filter(routeDefinition -> routes |
||||
.contains(routeDefinition.getId())) |
||||
.forEach(routeDefinition -> routeDefinition.getPredicates().stream() |
||||
.filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName())) |
||||
.filter(predicateDefinition -> !"ruoyi-auth".equalsIgnoreCase(routeDefinition.getId())) |
||||
.forEach(predicateDefinition -> resourceList |
||||
.add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs() |
||||
.get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", SWAGGER2URL))))); |
||||
return resourceList; |
||||
} |
||||
|
||||
private SwaggerResource swaggerResource(String name, String location) |
||||
{ |
||||
SwaggerResource swaggerResource = new SwaggerResource(); |
||||
swaggerResource.setName(name); |
||||
swaggerResource.setLocation(location); |
||||
swaggerResource.setSwaggerVersion("2.0"); |
||||
return swaggerResource; |
||||
} |
||||
|
||||
@Override |
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) |
||||
{ |
||||
/** swagger-ui 地址 */ |
||||
registry.addResourceHandler("/swagger-ui/**") |
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); |
||||
} |
||||
} |
||||
package com.yisai.gateway.config; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.cloud.gateway.config.GatewayProperties; |
||||
import org.springframework.cloud.gateway.route.RouteLocator; |
||||
import org.springframework.cloud.gateway.support.NameUtils; |
||||
import org.springframework.context.annotation.Lazy; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.reactive.config.ResourceHandlerRegistry; |
||||
import org.springframework.web.reactive.config.WebFluxConfigurer; |
||||
import springfox.documentation.swagger.web.SwaggerResource; |
||||
import springfox.documentation.swagger.web.SwaggerResourcesProvider; |
||||
|
||||
/** |
||||
* 聚合系统接口 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class SwaggerProvider implements SwaggerResourcesProvider, WebFluxConfigurer |
||||
{ |
||||
/** |
||||
* Swagger2默认的url后缀 |
||||
*/ |
||||
public static final String SWAGGER2URL = "/v2/api-docs"; |
||||
|
||||
/** |
||||
* 网关路由 |
||||
*/ |
||||
@Lazy |
||||
@Autowired |
||||
private RouteLocator routeLocator; |
||||
|
||||
@Autowired |
||||
private GatewayProperties gatewayProperties; |
||||
|
||||
/** |
||||
* 聚合其他服务接口 |
||||
* |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public List<SwaggerResource> get() |
||||
{ |
||||
List<SwaggerResource> resourceList = new ArrayList<>(); |
||||
List<String> routes = new ArrayList<>(); |
||||
// 获取网关中配置的route
|
||||
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); |
||||
gatewayProperties.getRoutes().stream() |
||||
.filter(routeDefinition -> routes |
||||
.contains(routeDefinition.getId())) |
||||
.forEach(routeDefinition -> routeDefinition.getPredicates().stream() |
||||
.filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName())) |
||||
.filter(predicateDefinition -> !"ruoyi-auth".equalsIgnoreCase(routeDefinition.getId())) |
||||
.forEach(predicateDefinition -> resourceList |
||||
.add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs() |
||||
.get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", SWAGGER2URL))))); |
||||
return resourceList; |
||||
} |
||||
|
||||
private SwaggerResource swaggerResource(String name, String location) |
||||
{ |
||||
SwaggerResource swaggerResource = new SwaggerResource(); |
||||
swaggerResource.setName(name); |
||||
swaggerResource.setLocation(location); |
||||
swaggerResource.setSwaggerVersion("2.0"); |
||||
return swaggerResource; |
||||
} |
||||
|
||||
@Override |
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) |
||||
{ |
||||
/** swagger-ui 地址 */ |
||||
registry.addResourceHandler("/swagger-ui/**") |
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); |
||||
} |
||||
} |
@ -1,46 +1,46 @@
@@ -1,46 +1,46 @@
|
||||
package com.ruoyi.gateway.config.properties; |
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.cloud.context.config.annotation.RefreshScope; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* 验证码配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
@RefreshScope |
||||
@ConfigurationProperties(prefix = "security.captcha") |
||||
public class CaptchaProperties |
||||
{ |
||||
/** |
||||
* 验证码开关 |
||||
*/ |
||||
private Boolean enabled; |
||||
|
||||
/** |
||||
* 验证码类型(math 数组计算 char 字符) |
||||
*/ |
||||
private String type; |
||||
|
||||
public Boolean getEnabled() |
||||
{ |
||||
return enabled; |
||||
} |
||||
|
||||
public void setEnabled(Boolean enabled) |
||||
{ |
||||
this.enabled = enabled; |
||||
} |
||||
|
||||
public String getType() |
||||
{ |
||||
return type; |
||||
} |
||||
|
||||
public void setType(String type) |
||||
{ |
||||
this.type = type; |
||||
} |
||||
} |
||||
package com.yisai.gateway.config.properties; |
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.cloud.context.config.annotation.RefreshScope; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* 验证码配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
@RefreshScope |
||||
@ConfigurationProperties(prefix = "security.captcha") |
||||
public class CaptchaProperties |
||||
{ |
||||
/** |
||||
* 验证码开关 |
||||
*/ |
||||
private Boolean enabled; |
||||
|
||||
/** |
||||
* 验证码类型(math 数组计算 char 字符) |
||||
*/ |
||||
private String type; |
||||
|
||||
public Boolean getEnabled() |
||||
{ |
||||
return enabled; |
||||
} |
||||
|
||||
public void setEnabled(Boolean enabled) |
||||
{ |
||||
this.enabled = enabled; |
||||
} |
||||
|
||||
public String getType() |
||||
{ |
||||
return type; |
||||
} |
||||
|
||||
public void setType(String type) |
||||
{ |
||||
this.type = type; |
||||
} |
||||
} |
@ -1,33 +1,33 @@
@@ -1,33 +1,33 @@
|
||||
package com.ruoyi.gateway.config.properties; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.cloud.context.config.annotation.RefreshScope; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* 放行白名单配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
@RefreshScope |
||||
@ConfigurationProperties(prefix = "security.ignore") |
||||
public class IgnoreWhiteProperties |
||||
{ |
||||
/** |
||||
* 放行白名单配置,网关不校验此处的白名单 |
||||
*/ |
||||
private List<String> whites = new ArrayList<>(); |
||||
|
||||
public List<String> getWhites() |
||||
{ |
||||
return whites; |
||||
} |
||||
|
||||
public void setWhites(List<String> whites) |
||||
{ |
||||
this.whites = whites; |
||||
} |
||||
} |
||||
package com.yisai.gateway.config.properties; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.cloud.context.config.annotation.RefreshScope; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* 放行白名单配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
@RefreshScope |
||||
@ConfigurationProperties(prefix = "security.ignore") |
||||
public class IgnoreWhiteProperties |
||||
{ |
||||
/** |
||||
* 放行白名单配置,网关不校验此处的白名单 |
||||
*/ |
||||
private List<String> whites = new ArrayList<>(); |
||||
|
||||
public List<String> getWhites() |
||||
{ |
||||
return whites; |
||||
} |
||||
|
||||
public void setWhites(List<String> whites) |
||||
{ |
||||
this.whites = whites; |
||||
} |
||||
} |
@ -1,48 +1,48 @@
@@ -1,48 +1,48 @@
|
||||
package com.ruoyi.gateway.config.properties; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.cloud.context.config.annotation.RefreshScope; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* XSS跨站脚本配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
@RefreshScope |
||||
@ConfigurationProperties(prefix = "security.xss") |
||||
public class XssProperties |
||||
{ |
||||
/** |
||||
* Xss开关 |
||||
*/ |
||||
private Boolean enabled; |
||||
|
||||
/** |
||||
* 排除路径 |
||||
*/ |
||||
private List<String> excludeUrls = new ArrayList<>(); |
||||
|
||||
public Boolean getEnabled() |
||||
{ |
||||
return enabled; |
||||
} |
||||
|
||||
public void setEnabled(Boolean enabled) |
||||
{ |
||||
this.enabled = enabled; |
||||
} |
||||
|
||||
public List<String> getExcludeUrls() |
||||
{ |
||||
return excludeUrls; |
||||
} |
||||
|
||||
public void setExcludeUrls(List<String> excludeUrls) |
||||
{ |
||||
this.excludeUrls = excludeUrls; |
||||
} |
||||
} |
||||
package com.yisai.gateway.config.properties; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.cloud.context.config.annotation.RefreshScope; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* XSS跨站脚本配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
@RefreshScope |
||||
@ConfigurationProperties(prefix = "security.xss") |
||||
public class XssProperties |
||||
{ |
||||
/** |
||||
* Xss开关 |
||||
*/ |
||||
private Boolean enabled; |
||||
|
||||
/** |
||||
* 排除路径 |
||||
*/ |
||||
private List<String> excludeUrls = new ArrayList<>(); |
||||
|
||||
public Boolean getEnabled() |
||||
{ |
||||
return enabled; |
||||
} |
||||
|
||||
public void setEnabled(Boolean enabled) |
||||
{ |
||||
this.enabled = enabled; |
||||
} |
||||
|
||||
public List<String> getExcludeUrls() |
||||
{ |
||||
return excludeUrls; |
||||
} |
||||
|
||||
public void setExcludeUrls(List<String> excludeUrls) |
||||
{ |
||||
this.excludeUrls = excludeUrls; |
||||
} |
||||
} |
@ -1,14 +1,9 @@
@@ -1,14 +1,9 @@
|
||||
package com.ruoyi.gateway.constant; |
||||
package com.yisai.gateway.constant; |
||||
|
||||
import com.ruoyi.gateway.filter.AuthFilter; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
|
||||
import java.util.List; |
||||
import java.util.Locale; |
||||
import java.util.logging.Logger; |
||||
|
||||
public class MessagesConstant { |
||||
private static final org.slf4j.Logger log = LoggerFactory.getLogger(MessagesConstant.class); |
||||
/**令牌不能为空*/ |
@ -1,67 +1,67 @@
@@ -1,67 +1,67 @@
|
||||
package com.ruoyi.gateway.filter; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import com.ruoyi.gateway.constant.MessagesConstant; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilter; |
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; |
||||
import org.springframework.stereotype.Component; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
|
||||
/** |
||||
* 黑名单过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config> |
||||
{ |
||||
@Override |
||||
public GatewayFilter apply(Config config) |
||||
{ |
||||
return (exchange, chain) -> { |
||||
|
||||
String url = exchange.getRequest().getURI().getPath(); |
||||
if (config.matchBlacklist(url)) |
||||
{ |
||||
return ServletUtils.webFluxResponseWriter(exchange.getResponse(), MessagesConstant.getMessages(exchange,MessagesConstant.MESSAGES_REQUEST_ADDRESS_ZH,MessagesConstant.MESSAGES_REQUEST_ADDRESS_EN)); |
||||
} |
||||
|
||||
return chain.filter(exchange); |
||||
}; |
||||
} |
||||
|
||||
public BlackListUrlFilter() |
||||
{ |
||||
super(Config.class); |
||||
} |
||||
|
||||
public static class Config |
||||
{ |
||||
private List<String> blacklistUrl; |
||||
|
||||
private List<Pattern> blacklistUrlPattern = new ArrayList<>(); |
||||
|
||||
public boolean matchBlacklist(String url) |
||||
{ |
||||
return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find()); |
||||
} |
||||
|
||||
public List<String> getBlacklistUrl() |
||||
{ |
||||
return blacklistUrl; |
||||
} |
||||
|
||||
public void setBlacklistUrl(List<String> blacklistUrl) |
||||
{ |
||||
this.blacklistUrl = blacklistUrl; |
||||
this.blacklistUrlPattern.clear(); |
||||
this.blacklistUrl.forEach(url -> { |
||||
this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE)); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
} |
||||
package com.yisai.gateway.filter; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import com.yisai.gateway.constant.MessagesConstant; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilter; |
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; |
||||
import org.springframework.stereotype.Component; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
|
||||
/** |
||||
* 黑名单过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config> |
||||
{ |
||||
@Override |
||||
public GatewayFilter apply(Config config) |
||||
{ |
||||
return (exchange, chain) -> { |
||||
|
||||
String url = exchange.getRequest().getURI().getPath(); |
||||
if (config.matchBlacklist(url)) |
||||
{ |
||||
return ServletUtils.webFluxResponseWriter(exchange.getResponse(), MessagesConstant.getMessages(exchange,MessagesConstant.MESSAGES_REQUEST_ADDRESS_ZH,MessagesConstant.MESSAGES_REQUEST_ADDRESS_EN)); |
||||
} |
||||
|
||||
return chain.filter(exchange); |
||||
}; |
||||
} |
||||
|
||||
public BlackListUrlFilter() |
||||
{ |
||||
super(Config.class); |
||||
} |
||||
|
||||
public static class Config |
||||
{ |
||||
private List<String> blacklistUrl; |
||||
|
||||
private List<Pattern> blacklistUrlPattern = new ArrayList<>(); |
||||
|
||||
public boolean matchBlacklist(String url) |
||||
{ |
||||
return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find()); |
||||
} |
||||
|
||||
public List<String> getBlacklistUrl() |
||||
{ |
||||
return blacklistUrl; |
||||
} |
||||
|
||||
public void setBlacklistUrl(List<String> blacklistUrl) |
||||
{ |
||||
this.blacklistUrl = blacklistUrl; |
||||
this.blacklistUrlPattern.clear(); |
||||
this.blacklistUrl.forEach(url -> { |
||||
this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE)); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
package com.ruoyi.gateway.filter; |
||||
package com.yisai.gateway.filter; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
@ -1,79 +1,80 @@
@@ -1,79 +1,80 @@
|
||||
package com.ruoyi.gateway.filter; |
||||
|
||||
import java.nio.CharBuffer; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.util.concurrent.atomic.AtomicReference; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilter; |
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; |
||||
import org.springframework.core.io.buffer.DataBuffer; |
||||
import org.springframework.core.io.buffer.DataBufferUtils; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.stereotype.Component; |
||||
import com.alibaba.fastjson2.JSON; |
||||
import com.alibaba.fastjson2.JSONObject; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
import com.ruoyi.gateway.config.properties.CaptchaProperties; |
||||
import com.ruoyi.gateway.service.ValidateCodeService; |
||||
import reactor.core.publisher.Flux; |
||||
|
||||
/** |
||||
* 验证码过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object> |
||||
{ |
||||
private final static String[] VALIDATE_URL = new String[] { "/auth/login", "/auth/register" }; |
||||
|
||||
@Autowired |
||||
private ValidateCodeService validateCodeService; |
||||
|
||||
@Autowired |
||||
private CaptchaProperties captchaProperties; |
||||
|
||||
private static final String CODE = "code"; |
||||
|
||||
private static final String UUID = "uuid"; |
||||
|
||||
@Override |
||||
public GatewayFilter apply(Object config) |
||||
{ |
||||
return (exchange, chain) -> { |
||||
ServerHttpRequest request = exchange.getRequest(); |
||||
|
||||
// 非登录/注册请求或验证码关闭,不处理
|
||||
if (!StringUtils.containsAnyIgnoreCase(request.getURI().getPath(), VALIDATE_URL) || !captchaProperties.getEnabled()) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
|
||||
try |
||||
{ |
||||
String rspStr = resolveBodyFromRequest(request); |
||||
JSONObject obj = JSON.parseObject(rspStr); |
||||
validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID)); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage()); |
||||
} |
||||
return chain.filter(exchange); |
||||
}; |
||||
} |
||||
|
||||
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) |
||||
{ |
||||
// 获取请求体
|
||||
Flux<DataBuffer> body = serverHttpRequest.getBody(); |
||||
AtomicReference<String> bodyRef = new AtomicReference<>(); |
||||
body.subscribe(buffer -> { |
||||
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); |
||||
DataBufferUtils.release(buffer); |
||||
bodyRef.set(charBuffer.toString()); |
||||
}); |
||||
return bodyRef.get(); |
||||
} |
||||
} |
||||
package com.yisai.gateway.filter; |
||||
|
||||
import java.nio.CharBuffer; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.util.concurrent.atomic.AtomicReference; |
||||
|
||||
import com.yisai.gateway.config.properties.CaptchaProperties; |
||||
import com.yisai.gateway.service.ValidateCodeService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilter; |
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; |
||||
import org.springframework.core.io.buffer.DataBuffer; |
||||
import org.springframework.core.io.buffer.DataBufferUtils; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.stereotype.Component; |
||||
import com.alibaba.fastjson2.JSON; |
||||
import com.alibaba.fastjson2.JSONObject; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
import reactor.core.publisher.Flux; |
||||
|
||||
/** |
||||
* 验证码过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object> |
||||
{ |
||||
private final static String[] VALIDATE_URL = new String[] { "/auth/login", "/auth/register" }; |
||||
|
||||
@Autowired |
||||
private ValidateCodeService validateCodeService; |
||||
|
||||
@Autowired |
||||
private CaptchaProperties captchaProperties; |
||||
|
||||
private static final String CODE = "code"; |
||||
|
||||
private static final String UUID = "uuid"; |
||||
|
||||
@Override |
||||
public GatewayFilter apply(Object config) |
||||
{ |
||||
return (exchange, chain) -> { |
||||
ServerHttpRequest request = exchange.getRequest(); |
||||
|
||||
// 非登录/注册请求或验证码关闭,不处理
|
||||
if (!StringUtils.containsAnyIgnoreCase(request.getURI().getPath(), VALIDATE_URL) || !captchaProperties.getEnabled()) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
|
||||
try |
||||
{ |
||||
String rspStr = resolveBodyFromRequest(request); |
||||
JSONObject obj = JSON.parseObject(rspStr); |
||||
validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID)); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage()); |
||||
} |
||||
return chain.filter(exchange); |
||||
}; |
||||
} |
||||
|
||||
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) |
||||
{ |
||||
// 获取请求体
|
||||
Flux<DataBuffer> body = serverHttpRequest.getBody(); |
||||
AtomicReference<String> bodyRef = new AtomicReference<>(); |
||||
body.subscribe(buffer -> { |
||||
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); |
||||
DataBufferUtils.release(buffer); |
||||
bodyRef.set(charBuffer.toString()); |
||||
}); |
||||
return bodyRef.get(); |
||||
} |
||||
} |
@ -1,124 +1,124 @@
@@ -1,124 +1,124 @@
|
||||
package com.ruoyi.gateway.filter; |
||||
|
||||
import java.nio.charset.StandardCharsets; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
||||
import org.springframework.cloud.gateway.filter.GlobalFilter; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.core.io.buffer.DataBuffer; |
||||
import org.springframework.core.io.buffer.DataBufferFactory; |
||||
import org.springframework.core.io.buffer.DataBufferUtils; |
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory; |
||||
import org.springframework.core.io.buffer.NettyDataBufferFactory; |
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
import com.ruoyi.common.core.utils.html.EscapeUtil; |
||||
import com.ruoyi.gateway.config.properties.XssProperties; |
||||
import io.netty.buffer.ByteBufAllocator; |
||||
import reactor.core.publisher.Flux; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 跨站脚本过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true") |
||||
public class XssFilter implements GlobalFilter, Ordered |
||||
{ |
||||
// 跨站脚本的 xss 配置,nacos自行添加
|
||||
@Autowired |
||||
private XssProperties xss; |
||||
|
||||
@Override |
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) |
||||
{ |
||||
ServerHttpRequest request = exchange.getRequest(); |
||||
// GET DELETE 不过滤
|
||||
HttpMethod method = request.getMethod(); |
||||
if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
// 非json类型,不过滤
|
||||
if (!isJsonRequest(exchange)) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
// excludeUrls 不过滤
|
||||
String url = request.getURI().getPath(); |
||||
if (StringUtils.matches(url, xss.getExcludeUrls())) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); |
||||
return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); |
||||
|
||||
} |
||||
|
||||
private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) |
||||
{ |
||||
ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) |
||||
{ |
||||
@Override |
||||
public Flux<DataBuffer> getBody() |
||||
{ |
||||
Flux<DataBuffer> body = super.getBody(); |
||||
return body.buffer().map(dataBuffers -> { |
||||
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); |
||||
DataBuffer join = dataBufferFactory.join(dataBuffers); |
||||
byte[] content = new byte[join.readableByteCount()]; |
||||
join.read(content); |
||||
DataBufferUtils.release(join); |
||||
String bodyStr = new String(content, StandardCharsets.UTF_8); |
||||
// 防xss攻击过滤
|
||||
bodyStr = EscapeUtil.clean(bodyStr); |
||||
// 转成字节
|
||||
byte[] bytes = bodyStr.getBytes(); |
||||
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); |
||||
DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); |
||||
buffer.write(bytes); |
||||
return buffer; |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
public HttpHeaders getHeaders() |
||||
{ |
||||
HttpHeaders httpHeaders = new HttpHeaders(); |
||||
httpHeaders.putAll(super.getHeaders()); |
||||
// 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length
|
||||
httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); |
||||
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); |
||||
return httpHeaders; |
||||
} |
||||
|
||||
}; |
||||
return serverHttpRequestDecorator; |
||||
} |
||||
|
||||
/** |
||||
* 是否是Json请求 |
||||
* |
||||
* @param exchange HTTP请求 |
||||
*/ |
||||
public boolean isJsonRequest(ServerWebExchange exchange) |
||||
{ |
||||
String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); |
||||
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); |
||||
} |
||||
|
||||
@Override |
||||
public int getOrder() |
||||
{ |
||||
return -100; |
||||
} |
||||
} |
||||
package com.yisai.gateway.filter; |
||||
|
||||
import java.nio.charset.StandardCharsets; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
||||
import org.springframework.cloud.gateway.filter.GlobalFilter; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.core.io.buffer.DataBuffer; |
||||
import org.springframework.core.io.buffer.DataBufferFactory; |
||||
import org.springframework.core.io.buffer.DataBufferUtils; |
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory; |
||||
import org.springframework.core.io.buffer.NettyDataBufferFactory; |
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.http.server.reactive.ServerHttpRequest; |
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
import com.ruoyi.common.core.utils.html.EscapeUtil; |
||||
import com.yisai.gateway.config.properties.XssProperties; |
||||
import io.netty.buffer.ByteBufAllocator; |
||||
import reactor.core.publisher.Flux; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 跨站脚本过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true") |
||||
public class XssFilter implements GlobalFilter, Ordered |
||||
{ |
||||
// 跨站脚本的 xss 配置,nacos自行添加
|
||||
@Autowired |
||||
private XssProperties xss; |
||||
|
||||
@Override |
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) |
||||
{ |
||||
ServerHttpRequest request = exchange.getRequest(); |
||||
// GET DELETE 不过滤
|
||||
HttpMethod method = request.getMethod(); |
||||
if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
// 非json类型,不过滤
|
||||
if (!isJsonRequest(exchange)) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
// excludeUrls 不过滤
|
||||
String url = request.getURI().getPath(); |
||||
if (StringUtils.matches(url, xss.getExcludeUrls())) |
||||
{ |
||||
return chain.filter(exchange); |
||||
} |
||||
ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); |
||||
return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); |
||||
|
||||
} |
||||
|
||||
private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) |
||||
{ |
||||
ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) |
||||
{ |
||||
@Override |
||||
public Flux<DataBuffer> getBody() |
||||
{ |
||||
Flux<DataBuffer> body = super.getBody(); |
||||
return body.buffer().map(dataBuffers -> { |
||||
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); |
||||
DataBuffer join = dataBufferFactory.join(dataBuffers); |
||||
byte[] content = new byte[join.readableByteCount()]; |
||||
join.read(content); |
||||
DataBufferUtils.release(join); |
||||
String bodyStr = new String(content, StandardCharsets.UTF_8); |
||||
// 防xss攻击过滤
|
||||
bodyStr = EscapeUtil.clean(bodyStr); |
||||
// 转成字节
|
||||
byte[] bytes = bodyStr.getBytes(); |
||||
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); |
||||
DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); |
||||
buffer.write(bytes); |
||||
return buffer; |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
public HttpHeaders getHeaders() |
||||
{ |
||||
HttpHeaders httpHeaders = new HttpHeaders(); |
||||
httpHeaders.putAll(super.getHeaders()); |
||||
// 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length
|
||||
httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); |
||||
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); |
||||
return httpHeaders; |
||||
} |
||||
|
||||
}; |
||||
return serverHttpRequestDecorator; |
||||
} |
||||
|
||||
/** |
||||
* 是否是Json请求 |
||||
* |
||||
* @param exchange HTTP请求 |
||||
*/ |
||||
public boolean isJsonRequest(ServerWebExchange exchange) |
||||
{ |
||||
String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); |
||||
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); |
||||
} |
||||
|
||||
@Override |
||||
public int getOrder() |
||||
{ |
||||
return -100; |
||||
} |
||||
} |
@ -1,63 +1,63 @@
@@ -1,63 +1,63 @@
|
||||
package com.ruoyi.gateway.handler; |
||||
|
||||
import com.ruoyi.gateway.constant.MessagesConstant; |
||||
import org.springframework.cloud.gateway.support.NotFoundException; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.annotation.Order; |
||||
import org.springframework.http.server.reactive.ServerHttpResponse; |
||||
import org.springframework.web.server.ResponseStatusException; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 网关统一异常处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Order(-1) |
||||
@Configuration |
||||
public class GatewayExceptionHandler implements ErrorWebExceptionHandler |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class); |
||||
|
||||
@Override |
||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) |
||||
{ |
||||
ServerHttpResponse response = exchange.getResponse(); |
||||
|
||||
if (exchange.getResponse().isCommitted()) |
||||
{ |
||||
return Mono.error(ex); |
||||
} |
||||
|
||||
String msg; |
||||
|
||||
if (ex instanceof NotFoundException) |
||||
{ |
||||
/**服务未找到*/ |
||||
msg =MessagesConstant.getMessages(exchange,MessagesConstant.MESSAGES_SERVICE_NOT_FOUND_ZH,MessagesConstant.MESSAGES_SERVICE_NOT_FOUND_EN); |
||||
|
||||
} |
||||
else if (ex instanceof ResponseStatusException) |
||||
{ |
||||
ResponseStatusException responseStatusException = (ResponseStatusException) ex; |
||||
msg = responseStatusException.getMessage(); |
||||
} |
||||
else |
||||
{ |
||||
/**内部服务器错误*/ |
||||
//msg="内部服务器错误";
|
||||
msg =MessagesConstant.getMessages(exchange,MessagesConstant.MESSAGES_INTERNAL_SERVER_ERROR_ZH,MessagesConstant.MESSAGES_INTERNAL_SERVER_ERROR_EN); |
||||
} |
||||
|
||||
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage()); |
||||
|
||||
return ServletUtils.webFluxResponseWriter(response, msg); |
||||
} |
||||
|
||||
|
||||
package com.yisai.gateway.handler; |
||||
|
||||
import com.yisai.gateway.constant.MessagesConstant; |
||||
import org.springframework.cloud.gateway.support.NotFoundException; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.annotation.Order; |
||||
import org.springframework.http.server.reactive.ServerHttpResponse; |
||||
import org.springframework.web.server.ResponseStatusException; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 网关统一异常处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Order(-1) |
||||
@Configuration |
||||
public class GatewayExceptionHandler implements ErrorWebExceptionHandler |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class); |
||||
|
||||
@Override |
||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) |
||||
{ |
||||
ServerHttpResponse response = exchange.getResponse(); |
||||
|
||||
if (exchange.getResponse().isCommitted()) |
||||
{ |
||||
return Mono.error(ex); |
||||
} |
||||
|
||||
String msg; |
||||
|
||||
if (ex instanceof NotFoundException) |
||||
{ |
||||
/**服务未找到*/ |
||||
msg =MessagesConstant.getMessages(exchange,MessagesConstant.MESSAGES_SERVICE_NOT_FOUND_ZH,MessagesConstant.MESSAGES_SERVICE_NOT_FOUND_EN); |
||||
|
||||
} |
||||
else if (ex instanceof ResponseStatusException) |
||||
{ |
||||
ResponseStatusException responseStatusException = (ResponseStatusException) ex; |
||||
msg = responseStatusException.getMessage(); |
||||
} |
||||
else |
||||
{ |
||||
/**内部服务器错误*/ |
||||
//msg="内部服务器错误";
|
||||
msg =MessagesConstant.getMessages(exchange,MessagesConstant.MESSAGES_INTERNAL_SERVER_ERROR_ZH,MessagesConstant.MESSAGES_INTERNAL_SERVER_ERROR_EN); |
||||
} |
||||
|
||||
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage()); |
||||
|
||||
return ServletUtils.webFluxResponseWriter(response, msg); |
||||
} |
||||
|
||||
|
||||
} |
@ -1,41 +1,41 @@
@@ -1,41 +1,41 @@
|
||||
package com.ruoyi.gateway.handler; |
||||
|
||||
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; |
||||
import com.alibaba.csp.sentinel.slots.block.BlockException; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
import org.springframework.web.reactive.function.server.ServerResponse; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import org.springframework.web.server.WebExceptionHandler; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 自定义限流异常处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class SentinelFallbackHandler implements WebExceptionHandler |
||||
{ |
||||
private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) |
||||
{ |
||||
return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试"); |
||||
} |
||||
|
||||
@Override |
||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) |
||||
{ |
||||
if (exchange.getResponse().isCommitted()) |
||||
{ |
||||
return Mono.error(ex); |
||||
} |
||||
if (!BlockException.isBlockException(ex)) |
||||
{ |
||||
return Mono.error(ex); |
||||
} |
||||
return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange)); |
||||
} |
||||
|
||||
private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) |
||||
{ |
||||
return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); |
||||
} |
||||
} |
||||
package com.yisai.gateway.handler; |
||||
|
||||
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; |
||||
import com.alibaba.csp.sentinel.slots.block.BlockException; |
||||
import com.ruoyi.common.core.utils.ServletUtils; |
||||
import org.springframework.web.reactive.function.server.ServerResponse; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
import org.springframework.web.server.WebExceptionHandler; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 自定义限流异常处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class SentinelFallbackHandler implements WebExceptionHandler |
||||
{ |
||||
private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) |
||||
{ |
||||
return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试"); |
||||
} |
||||
|
||||
@Override |
||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) |
||||
{ |
||||
if (exchange.getResponse().isCommitted()) |
||||
{ |
||||
return Mono.error(ex); |
||||
} |
||||
if (!BlockException.isBlockException(ex)) |
||||
{ |
||||
return Mono.error(ex); |
||||
} |
||||
return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange)); |
||||
} |
||||
|
||||
private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) |
||||
{ |
||||
return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); |
||||
} |
||||
} |
@ -1,56 +1,56 @@
@@ -1,56 +1,56 @@
|
||||
package com.ruoyi.gateway.handler; |
||||
|
||||
import java.util.Optional; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import reactor.core.publisher.Mono; |
||||
import springfox.documentation.swagger.web.SecurityConfiguration; |
||||
import springfox.documentation.swagger.web.SecurityConfigurationBuilder; |
||||
import springfox.documentation.swagger.web.SwaggerResourcesProvider; |
||||
import springfox.documentation.swagger.web.UiConfiguration; |
||||
import springfox.documentation.swagger.web.UiConfigurationBuilder; |
||||
|
||||
@RestController |
||||
@RequestMapping("/swagger-resources") |
||||
public class SwaggerHandler |
||||
{ |
||||
@Autowired(required = false) |
||||
private SecurityConfiguration securityConfiguration; |
||||
|
||||
@Autowired(required = false) |
||||
private UiConfiguration uiConfiguration; |
||||
|
||||
private final SwaggerResourcesProvider swaggerResources; |
||||
|
||||
@Autowired |
||||
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) |
||||
{ |
||||
this.swaggerResources = swaggerResources; |
||||
} |
||||
|
||||
@GetMapping("/configuration/security") |
||||
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() |
||||
{ |
||||
return Mono.just(new ResponseEntity<>( |
||||
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), |
||||
HttpStatus.OK)); |
||||
} |
||||
|
||||
@GetMapping("/configuration/ui") |
||||
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() |
||||
{ |
||||
return Mono.just(new ResponseEntity<>( |
||||
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); |
||||
} |
||||
|
||||
@SuppressWarnings("rawtypes") |
||||
@GetMapping("") |
||||
public Mono<ResponseEntity> swaggerResources() |
||||
{ |
||||
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); |
||||
} |
||||
} |
||||
package com.yisai.gateway.handler; |
||||
|
||||
import java.util.Optional; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
import reactor.core.publisher.Mono; |
||||
import springfox.documentation.swagger.web.SecurityConfiguration; |
||||
import springfox.documentation.swagger.web.SecurityConfigurationBuilder; |
||||
import springfox.documentation.swagger.web.SwaggerResourcesProvider; |
||||
import springfox.documentation.swagger.web.UiConfiguration; |
||||
import springfox.documentation.swagger.web.UiConfigurationBuilder; |
||||
|
||||
@RestController |
||||
@RequestMapping("/swagger-resources") |
||||
public class SwaggerHandler |
||||
{ |
||||
@Autowired(required = false) |
||||
private SecurityConfiguration securityConfiguration; |
||||
|
||||
@Autowired(required = false) |
||||
private UiConfiguration uiConfiguration; |
||||
|
||||
private final SwaggerResourcesProvider swaggerResources; |
||||
|
||||
@Autowired |
||||
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) |
||||
{ |
||||
this.swaggerResources = swaggerResources; |
||||
} |
||||
|
||||
@GetMapping("/configuration/security") |
||||
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() |
||||
{ |
||||
return Mono.just(new ResponseEntity<>( |
||||
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), |
||||
HttpStatus.OK)); |
||||
} |
||||
|
||||
@GetMapping("/configuration/ui") |
||||
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() |
||||
{ |
||||
return Mono.just(new ResponseEntity<>( |
||||
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); |
||||
} |
||||
|
||||
@SuppressWarnings("rawtypes") |
||||
@GetMapping("") |
||||
public Mono<ResponseEntity> swaggerResources() |
||||
{ |
||||
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); |
||||
} |
||||
} |
@ -1,41 +1,41 @@
@@ -1,41 +1,41 @@
|
||||
package com.ruoyi.gateway.handler; |
||||
|
||||
import java.io.IOException; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.reactive.function.BodyInserters; |
||||
import org.springframework.web.reactive.function.server.HandlerFunction; |
||||
import org.springframework.web.reactive.function.server.ServerRequest; |
||||
import org.springframework.web.reactive.function.server.ServerResponse; |
||||
import com.ruoyi.common.core.exception.CaptchaException; |
||||
import com.ruoyi.common.core.web.domain.AjaxResult; |
||||
import com.ruoyi.gateway.service.ValidateCodeService; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 验证码获取 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class ValidateCodeHandler implements HandlerFunction<ServerResponse> |
||||
{ |
||||
@Autowired |
||||
private ValidateCodeService validateCodeService; |
||||
|
||||
@Override |
||||
public Mono<ServerResponse> handle(ServerRequest serverRequest) |
||||
{ |
||||
AjaxResult ajax; |
||||
try |
||||
{ |
||||
ajax = validateCodeService.createCaptcha(); |
||||
} |
||||
catch (CaptchaException | IOException e) |
||||
{ |
||||
return Mono.error(e); |
||||
} |
||||
return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(ajax)); |
||||
} |
||||
} |
||||
package com.yisai.gateway.handler; |
||||
|
||||
import java.io.IOException; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.web.reactive.function.BodyInserters; |
||||
import org.springframework.web.reactive.function.server.HandlerFunction; |
||||
import org.springframework.web.reactive.function.server.ServerRequest; |
||||
import org.springframework.web.reactive.function.server.ServerResponse; |
||||
import com.ruoyi.common.core.exception.CaptchaException; |
||||
import com.ruoyi.common.core.web.domain.AjaxResult; |
||||
import com.yisai.gateway.service.ValidateCodeService; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* 验证码获取 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class ValidateCodeHandler implements HandlerFunction<ServerResponse> |
||||
{ |
||||
@Autowired |
||||
private ValidateCodeService validateCodeService; |
||||
|
||||
@Override |
||||
public Mono<ServerResponse> handle(ServerRequest serverRequest) |
||||
{ |
||||
AjaxResult ajax; |
||||
try |
||||
{ |
||||
ajax = validateCodeService.createCaptcha(); |
||||
} |
||||
catch (CaptchaException | IOException e) |
||||
{ |
||||
return Mono.error(e); |
||||
} |
||||
return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(ajax)); |
||||
} |
||||
} |
@ -1,23 +1,23 @@
@@ -1,23 +1,23 @@
|
||||
package com.ruoyi.gateway.service; |
||||
|
||||
import java.io.IOException; |
||||
import com.ruoyi.common.core.exception.CaptchaException; |
||||
import com.ruoyi.common.core.web.domain.AjaxResult; |
||||
|
||||
/** |
||||
* 验证码处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface ValidateCodeService |
||||
{ |
||||
/** |
||||
* 生成验证码 |
||||
*/ |
||||
public AjaxResult createCaptcha() throws IOException, CaptchaException; |
||||
|
||||
/** |
||||
* 校验验证码 |
||||
*/ |
||||
public void checkCaptcha(String key, String value) throws CaptchaException; |
||||
} |
||||
package com.yisai.gateway.service; |
||||
|
||||
import java.io.IOException; |
||||
import com.ruoyi.common.core.exception.CaptchaException; |
||||
import com.ruoyi.common.core.web.domain.AjaxResult; |
||||
|
||||
/** |
||||
* 验证码处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface ValidateCodeService |
||||
{ |
||||
/** |
||||
* 生成验证码 |
||||
*/ |
||||
public AjaxResult createCaptcha() throws IOException, CaptchaException; |
||||
|
||||
/** |
||||
* 校验验证码 |
||||
*/ |
||||
public void checkCaptcha(String key, String value) throws CaptchaException; |
||||
} |
@ -1,118 +1,118 @@
@@ -1,118 +1,118 @@
|
||||
package com.ruoyi.gateway.service.impl; |
||||
|
||||
import java.awt.image.BufferedImage; |
||||
import java.io.IOException; |
||||
import java.util.concurrent.TimeUnit; |
||||
import javax.annotation.Resource; |
||||
import javax.imageio.ImageIO; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.util.FastByteArrayOutputStream; |
||||
import com.google.code.kaptcha.Producer; |
||||
import com.ruoyi.common.core.constant.Constants; |
||||
import com.ruoyi.common.core.exception.CaptchaException; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
import com.ruoyi.common.core.utils.sign.Base64; |
||||
import com.ruoyi.common.core.utils.uuid.IdUtils; |
||||
import com.ruoyi.common.core.web.domain.AjaxResult; |
||||
import com.ruoyi.common.redis.service.RedisService; |
||||
import com.ruoyi.gateway.config.properties.CaptchaProperties; |
||||
import com.ruoyi.gateway.service.ValidateCodeService; |
||||
|
||||
/** |
||||
* 验证码实现处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Service |
||||
public class ValidateCodeServiceImpl implements ValidateCodeService |
||||
{ |
||||
@Resource(name = "captchaProducer") |
||||
private Producer captchaProducer; |
||||
|
||||
@Resource(name = "captchaProducerMath") |
||||
private Producer captchaProducerMath; |
||||
|
||||
@Autowired |
||||
private RedisService redisService; |
||||
|
||||
@Autowired |
||||
private CaptchaProperties captchaProperties; |
||||
|
||||
/** |
||||
* 生成验证码 |
||||
*/ |
||||
@Override |
||||
public AjaxResult createCaptcha() throws IOException, CaptchaException |
||||
{ |
||||
AjaxResult ajax = AjaxResult.success(); |
||||
boolean captchaOnOff = captchaProperties.getEnabled(); |
||||
ajax.put("captchaOnOff", captchaOnOff); |
||||
if (!captchaOnOff) |
||||
{ |
||||
return ajax; |
||||
} |
||||
|
||||
// 保存验证码信息
|
||||
String uuid = IdUtils.simpleUUID(); |
||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; |
||||
|
||||
String capStr = null, code = null; |
||||
BufferedImage image = null; |
||||
|
||||
String captchaType = captchaProperties.getType(); |
||||
// 生成验证码
|
||||
if ("math".equals(captchaType)) |
||||
{ |
||||
String capText = captchaProducerMath.createText(); |
||||
capStr = capText.substring(0, capText.lastIndexOf("@")); |
||||
code = capText.substring(capText.lastIndexOf("@") + 1); |
||||
image = captchaProducerMath.createImage(capStr); |
||||
} |
||||
else if ("char".equals(captchaType)) |
||||
{ |
||||
capStr = code = captchaProducer.createText(); |
||||
image = captchaProducer.createImage(capStr); |
||||
} |
||||
|
||||
redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); |
||||
// 转换流信息写出
|
||||
FastByteArrayOutputStream os = new FastByteArrayOutputStream(); |
||||
try |
||||
{ |
||||
ImageIO.write(image, "jpg", os); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
return AjaxResult.error(e.getMessage()); |
||||
} |
||||
|
||||
ajax.put("uuid", uuid); |
||||
ajax.put("img", Base64.encode(os.toByteArray())); |
||||
return ajax; |
||||
} |
||||
|
||||
/** |
||||
* 校验验证码 |
||||
*/ |
||||
@Override |
||||
public void checkCaptcha(String code, String uuid) throws CaptchaException |
||||
{ |
||||
if (StringUtils.isEmpty(code)) |
||||
{ |
||||
throw new CaptchaException("验证码不能为空"); |
||||
} |
||||
if (StringUtils.isEmpty(uuid)) |
||||
{ |
||||
throw new CaptchaException("验证码已失效"); |
||||
} |
||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; |
||||
String captcha = redisService.getCacheObject(verifyKey); |
||||
redisService.deleteObject(verifyKey); |
||||
|
||||
if (!code.equalsIgnoreCase(captcha)) |
||||
{ |
||||
throw new CaptchaException("验证码错误"); |
||||
} |
||||
} |
||||
} |
||||
package com.yisai.gateway.service.impl; |
||||
|
||||
import java.awt.image.BufferedImage; |
||||
import java.io.IOException; |
||||
import java.util.concurrent.TimeUnit; |
||||
import javax.annotation.Resource; |
||||
import javax.imageio.ImageIO; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.util.FastByteArrayOutputStream; |
||||
import com.google.code.kaptcha.Producer; |
||||
import com.ruoyi.common.core.constant.Constants; |
||||
import com.ruoyi.common.core.exception.CaptchaException; |
||||
import com.ruoyi.common.core.utils.StringUtils; |
||||
import com.ruoyi.common.core.utils.sign.Base64; |
||||
import com.ruoyi.common.core.utils.uuid.IdUtils; |
||||
import com.ruoyi.common.core.web.domain.AjaxResult; |
||||
import com.ruoyi.common.redis.service.RedisService; |
||||
import com.yisai.gateway.config.properties.CaptchaProperties; |
||||
import com.yisai.gateway.service.ValidateCodeService; |
||||
|
||||
/** |
||||
* 验证码实现处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Service |
||||
public class ValidateCodeServiceImpl implements ValidateCodeService |
||||
{ |
||||
@Resource(name = "captchaProducer") |
||||
private Producer captchaProducer; |
||||
|
||||
@Resource(name = "captchaProducerMath") |
||||
private Producer captchaProducerMath; |
||||
|
||||
@Autowired |
||||
private RedisService redisService; |
||||
|
||||
@Autowired |
||||
private CaptchaProperties captchaProperties; |
||||
|
||||
/** |
||||
* 生成验证码 |
||||
*/ |
||||
@Override |
||||
public AjaxResult createCaptcha() throws IOException, CaptchaException |
||||
{ |
||||
AjaxResult ajax = AjaxResult.success(); |
||||
boolean captchaOnOff = captchaProperties.getEnabled(); |
||||
ajax.put("captchaOnOff", captchaOnOff); |
||||
if (!captchaOnOff) |
||||
{ |
||||
return ajax; |
||||
} |
||||
|
||||
// 保存验证码信息
|
||||
String uuid = IdUtils.simpleUUID(); |
||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; |
||||
|
||||
String capStr = null, code = null; |
||||
BufferedImage image = null; |
||||
|
||||
String captchaType = captchaProperties.getType(); |
||||
// 生成验证码
|
||||
if ("math".equals(captchaType)) |
||||
{ |
||||
String capText = captchaProducerMath.createText(); |
||||
capStr = capText.substring(0, capText.lastIndexOf("@")); |
||||
code = capText.substring(capText.lastIndexOf("@") + 1); |
||||
image = captchaProducerMath.createImage(capStr); |
||||
} |
||||
else if ("char".equals(captchaType)) |
||||
{ |
||||
capStr = code = captchaProducer.createText(); |
||||
image = captchaProducer.createImage(capStr); |
||||
} |
||||
|
||||
redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); |
||||
// 转换流信息写出
|
||||
FastByteArrayOutputStream os = new FastByteArrayOutputStream(); |
||||
try |
||||
{ |
||||
ImageIO.write(image, "jpg", os); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
return AjaxResult.error(e.getMessage()); |
||||
} |
||||
|
||||
ajax.put("uuid", uuid); |
||||
ajax.put("img", Base64.encode(os.toByteArray())); |
||||
return ajax; |
||||
} |
||||
|
||||
/** |
||||
* 校验验证码 |
||||
*/ |
||||
@Override |
||||
public void checkCaptcha(String code, String uuid) throws CaptchaException |
||||
{ |
||||
if (StringUtils.isEmpty(code)) |
||||
{ |
||||
throw new CaptchaException("验证码不能为空"); |
||||
} |
||||
if (StringUtils.isEmpty(uuid)) |
||||
{ |
||||
throw new CaptchaException("验证码已失效"); |
||||
} |
||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; |
||||
String captcha = redisService.getCacheObject(verifyKey); |
||||
redisService.deleteObject(verifyKey); |
||||
|
||||
if (!code.equalsIgnoreCase(captcha)) |
||||
{ |
||||
throw new CaptchaException("验证码错误"); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue