import cn . hutool . core . date . DateUnit ; import cn . hutool . core . date . DateUtil ; import com . alibaba . fastjson . JSON ; import com . alibaba . fastjson . JSONObject ; import com . google . gson . Gson ; import com . * * * * . MD5Util ; import com . * * * * . SignUtils ; import com . * * * * . Result ; import lombok . extern . slf4j . Slf4j ; import org . apache . commons . lang3 . StringUtils ; import org . springframework . beans . factory . annotation . Autowired ; import org . springframework . cloud . gateway . filter . GatewayFilter ; import org . springframework . cloud . gateway . filter . GatewayFilterChain ; import org . springframework . cloud . gateway . filter . factory . AbstractGatewayFilterFactory ; import org . springframework . cloud . gateway . support . ipresolver . XForwardedRemoteAddressResolver ; import org . springframework . core . io . buffer . DataBuffer ; import org . springframework . data . redis . core . RedisTemplate ; import org . springframework . http . HttpHeaders ; import org . springframework . http . HttpStatus ; import org . springframework . http . MediaType ; import org . springframework . stereotype . Component ; import org . springframework . web . server . ServerWebExchange ; import reactor . core . publisher . Mono ; import java . net . InetSocketAddress ; import java . nio . charset . StandardCharsets ; import java . util . Arrays ; import java . util . Date ; import java . util . Map ; import java . util . TreeMap ; import java . util . concurrent . TimeUnit ; import static org . springframework . cloud . gateway . support . GatewayToStringStyler . filterToStringCreator ; * @author hk * @See com.kbd.watermelon.scheduleTask.EnterpriseApiKeyTask @Slf4j @Component public class AuthOpenApiGatewayFilterFactory extends AbstractGatewayFilterFactory < Object > { public static final String PREFIX = "ota:enterprise:api:" ; private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject" ; @Autowired private RedisTemplate < String , Object > redisTemplate ; public GatewayFilter apply ( ) { return apply ( o -> { } ) ; @Override public GatewayFilter apply ( Object config ) { return new GatewayFilter ( ) { @Override public Mono < Void > filter ( ServerWebExchange exchange , GatewayFilterChain chain ) { XForwardedRemoteAddressResolver resolver = XForwardedRemoteAddressResolver . maxTrustedIndex ( 1 ) ; InetSocketAddress inetSocketAddress = resolver . resolve ( exchange ) ; String userIp = inetSocketAddress . getAddress ( ) . getHostAddress ( ) ; HttpHeaders httpHeaders = exchange . getRequest ( ) . getHeaders ( ) ; log . info ( new Gson ( ) . toJson ( httpHeaders ) ) ; String body = exchange . getAttribute ( CACHE_REQUEST_BODY_OBJECT_KEY ) ; log . info ( "userIp:{},body:{}" , userIp , body ) ; TreeMap < String , Object > treeMap = JSONObject . parseObject ( body , TreeMap . class ) ; String timestamp = ( String ) treeMap . get ( SignUtils . TIMESTAMP ) ; if ( StringUtils . isBlank ( timestamp ) ) { log . error ( "timestamp不能为空" ) ; return getErrorMono ( exchange , "timestamp不能为空" ) ; if ( DateUtil . between ( new Date ( ) , new Date ( Long . parseLong ( timestamp ) ) , DateUnit . MINUTE ) > 5 ) { log . error ( "超时" ) ; return getErrorMono ( exchange , "超时" ) ; String accesskey = ( String ) treeMap . get ( SignUtils . ACCESS_KEY ) ; String nonce = ( String ) treeMap . get ( SignUtils . NONCE ) ; String sign = ( String ) treeMap . get ( SignUtils . SIGN ) ; if ( StringUtils . isBlank ( accesskey ) ) { log . error ( "accesskey超时" ) ; return getErrorMono ( exchange , "accesskey超时" ) ; if ( StringUtils . isBlank ( nonce ) ) { log . error ( "nonce超时" ) ; return getErrorMono ( exchange , "nonce超时" ) ; if ( StringUtils . isBlank ( sign ) ) { log . error ( "sign超时" ) ; return getErrorMono ( exchange , "sign超时" ) ; if ( ! redisTemplate . opsForValue ( ) . setIfAbsent ( sign , nonce , 6 , TimeUnit . MINUTES ) ) { log . error ( "超时" ) ; return getErrorMono ( exchange , "超时" ) ; Map map = ( Map ) redisTemplate . opsForValue ( ) . get ( PREFIX + accesskey ) ; if ( map == null || map . get ( SignUtils . SECRET_KEY ) == null || SignUtils . IP == null ) { log . error ( "查询不到密钥{}" , accesskey ) ; return getErrorMono ( exchange , "查询不到密钥" ) ; if ( ! Arrays . asList ( ( map . get ( SignUtils . IP ) + "" ) . split ( "," ) ) . contains ( userIp ) ) { log . error ( "ip不在白名单" ) ; return getErrorMono ( exchange , "ip不在白名单" ) ; if ( ! SignUtils . validSign ( treeMap , map . get ( SignUtils . SECRET_KEY ) + "" ) ) { log . error ( "验证签名失败" ) ; return getErrorMono ( exchange , "验证签名失败" ) ; return chain . filter ( exchange ) ; @Override public String toString ( ) { return filterToStringCreator ( AuthOpenApiGatewayFilterFactory . this ) . toString ( ) ; private Mono < Void > getErrorMono ( ServerWebExchange exchange , String msg ) { exchange . getResponse ( ) . setStatusCode ( HttpStatus . UNAUTHORIZED ) ; exchange . getResponse ( ) . getHeaders ( ) . setContentType ( MediaType . APPLICATION_JSON ) ; String fastResult = JSON . toJSONString ( Result . fail ( msg ) ) ; DataBuffer dataBuffer = exchange . getResponse ( ) . bufferFactory ( ) . allocateBuffer ( ) . write ( fastResult . getBytes ( StandardCharsets . UTF_8 ) ) ; return exchange . getResponse ( ) . writeWith ( Mono . just ( dataBuffer ) ) ; public static void main ( String [ ] args ) { TreeMap < String , String > treeMap = new TreeMap < > ( ) ; treeMap . put ( "timestamp" , System . currentTimeMillis ( ) + "" ) ; treeMap . put ( "nonce" , "1234567" ) ; treeMap . put ( "accessKey" , "1234" ) ; treeMap . put ( "a" , "a" ) ; treeMap . put ( "b" , "b" ) ; StringBuilder stringBuilder = new StringBuilder ( ) ; for ( Map . Entry < String , String > stringStringEntry : treeMap . entrySet ( ) ) { if ( ! stringStringEntry . getKey ( ) . equals ( "sign" ) ) { stringBuilder . append ( stringStringEntry . getKey ( ) ) ; stringBuilder . append ( "=" ) ; stringBuilder . append ( stringStringEntry . getValue ( ) ) ; stringBuilder . append ( "&" ) ; stringBuilder . append ( "secretKey=" ) ; stringBuilder . append ( "123" ) ; System . out . println ( stringBuilder . toString ( ) ) ; String md5 = MD5Util . md5 ( stringBuilder . toString ( ) ) ; treeMap . put ( "sign" , md5 ) ; System . out . println ( JSONObject . toJSON ( treeMap ) ) ;

SignUtils

public class SignUtils{
	public static final String SIGN = "sign";
	public static final String NONCE = "nonce";
	public static final String ACCESS_KEY = "accessKey";
	public static final String TIMESTAMP = "timestamp";
	public static final String SECRET_KEY = "secretKey";
	public static final String IP = "ip";
	public static boolean  validSign(TreeMap<String,Object> treeMap,String secret){
       StringBuilder stringBuilder = new StringBuilder();
       for(Map.Entry<String,Object> s :treeMap.entrySet()){
          if(!s.getKey().equals(SIGN)){
    		stringBuilder.append(s.getKey());
    		stringBuilder.append("=");
    		stringBuilder.append(s.getValue());
    		stringBuilder.append("&");
       stringBuilder.append(SECRET_KEY );
       stringBuilder.append("=");
       stringBuilder.append(secret);
       String md5 =MD5Util.md5(stringBuilder.toString());
       return md5.equalsIgnoreCase(treeMap.get("sign")+"");
import java.util.function.Predicate;
@Configuration
public class PredicateConfig{
  @Bean
  public Predicate bodPredicate(){
    return new Predicate(){
		@Override
		public boolean test(Object o ){return true;}

最后是yml 网关的配置

id: id
url: http://***
predicates:
 - Path=/openApi/**
 - name: ReadBody
   args:
     inClass: '#{T(String)}'
     predicate: '#{@bodyPredicate}'
filters:
 - AuthOpenApi
springdoc-openapi Java库有助于使用Spring Boot项目自动生成API文档。 springdoc-openapi的工作原理是在运行时检查应用程序以基于Spring配置,类结构和各种注释来推断API语义。
 该库会自动以JSON / YAML和HTML格式的页面生成文档。 可以使用swagger-api注释对生成的文档进行补充。
 该库支持:
 OpenAPI 3
 Spring启动(v1和v2)
 JSR-303,专门用于@ NotNull,@ Min,@ Max和@Size。
 Swagger-ui
 Oauth 2
 以下视频介绍了库:
 这是一个基于社区的项目,不是由Spring Framework Contributors(Pivotal)维护的
用于springdoc-openapispring-boot和swagger-ui集成的库
自动将swagger-ui部署到Spring Boot 2.x应用程序
使用官方的 ,将以HTML格式提供文档。
 然后,应该在可以找到Swagger UI页面,OpenAPI描述将在json格式的
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-webmvc-core</artifactId>
    <version>1.4.1</version>
</dependency>
我们的 gateway,S
OpenAPI规范(以前叫swagger规范)是一个接口文档规范,它用一个文件来描述API接口,包括:
可用的api接口(如/users) 和接口方法 (GET /users, POST /users)
输入和输出参数
鉴权方法
联系信息, 代码许可, 使用条款和其他信息等.
文件可是可以是json或yaml的,完整的规范参见: OpenAPI 3.0 Specification
什么是swagger
Swagger is a set of open-
本项目升级到基于Spring Boot 2.2版本和Spring Cloud Hoxton进行了开发的目的是简化和统一微服务框架Spring Boot和Spring Cloud的使用方法
通过一定的规则来统一编写各种依赖的Starter,方便在企业内部进行规则的统一,配置的统一,用法的统一,监控的统一,部署的统一方便再进一步简化Spring Boot和Spring Cloud的使用,进一步分离通用框架代码和业务代码的补充屏蔽部分的基础内容,减少业务开发对紧密基建处技术的了解,更加专注于业务的开发
loc-framework 2.0主要突破
升级基础依赖的Spring Boot 2.2和Spring Cloud Hoxton
使用springdoc-openapi代替springfox(springfox长期不进行更新,存在的一些错误得不到解决,需要一些功能得不到开发)
升级logbook到2.0.0大版本,提供更多的日志记录的功能
springdoc-openapi对比于springfox的区别
springdoc-openapi升级到了OpenAPI 3
注解使用了s
				
Spring Cloud Contract OpenAPI 3.0合约转换器 OpenAPI 3.0转换器 为RESTful API定义了一个与语言无关的标准接口,使人类和计算机都可以发现和理解服务的功能,而无需访问源代码,文档或通过网络流量检查。 正确定义后,使用者可以使用最少的实现逻辑来理解远程服务并与之交互。 然后,文档生成工具可以使用OpenAPI定义来显示API,代码生成工具可以使用各种编程语言,测试工具和许多其他用例来生成服务器和客户端。 提供一个完整的工作示例项目,该项目使用Open API 3.0定义Spring Cloud Contract的合同。 该项目是独立示例中常用的欺诈API示例的副本。 上面的示例实现了与相同的生产者,客户端和合同(在YAML中定义)。 要启用此插件,您将需要将OA3转换器jar添加到您的Spring Boot项目中,如
### 回答1: springdoc-openapi-ui是一个基于Spring Boot框架的开源项目,用于生成和展示API文档。它使用OpenAPI规范生成API文档,可以将API文档嵌入到应用程序中,使得API文档在应用程序内部可以直接访问。此外,它还提供了一些有用的功能,例如自动生成的API测试界面和请求示例。通过使用springdoc-openapi-ui,开发人员可以方便地创建和维护API文档,提高API的可用性和可理解性。 ### 回答2: Springdoc-openapi-ui是一个基于Spring框架构建的与OpenAPI规范相兼容的RESTful API文档生成器。它提供了开箱即用的代码生成器和集成了Swagger UI的一站式解决方案,可以帮助我们以更加简单快捷的方式生成和展示API文档。 Springdoc-openapi-ui提供了许多方便的功能,例如自动文档生成、API文档审核、API调试等,同时也支持通过扩展文档来标注业务逻辑,例如文档API、工作流、系统接口等等。此外,它还可以帮助我们快速构建RESTful API,并生成具有统一和可靠接口的相关文档。 值得注意的是,在使用Springdoc-openapi-ui时,我们需要按照OpenAPI规范编写API文档,而规范中提供的注解和规则都可以应用在我们的代码中。除此之外,集成了Swagger UI的Springdoc-openapi-ui还提供了强大的可视化界面管理功能,方便我们更加直观地查看并管理API文档。 总之,Springdoc-openapi-ui是一个非常实用的RESTful API文档生成器,它不仅可以帮助我们更加高效地生成和展示API文档,也可以帮助我们构建具有统一和可靠接口的RESTful API。如果您正在构建一个基于Spring框架的项目,并需要一个好的API文档生成器,那么Springdoc-openapi-ui一定是一个非常好的选择。 ### 回答3: Springdoc-openapi-ui是一款用于生成和渲染OpenAPI 3文档的Java库,它是基于Spring Boot和Spring WebMvc框架的自动生成OpenAPI 3文档。该库提供了一组API和Spring MVC扩展,它们共同工作来扫描Spring Web应用程序以生成OpenAPI文档。这使得开发人员可以快速轻松地为他们的REST API构建文档。 使用Springdoc-openapi-ui,开发人员可以很容易地定义规范来描述应用程序中的RESTful API,只需编写Swagger定义和Java注解即可定义API的路径,请求和返回值。同时,开发人员可以自定义API文档的样式并将其与项目集成,从而使API文档风格与应用程序一致。Springdoc-openapi-ui还支持几种不同的的文档格式,包括HTML,Json和YAML。 Springdoc-openapi-ui使用Swagger UI渲染API文档,它可以自动生成文档的HTML页面,并提供与API交互的用户界面。Swagger UI允许开发人员测试API调用并在开发期间检查和验证文档。它还支持代码生成工具,允许开发人员通过Swagger定义结合生成客户端代码。 总之,Springdoc-openapi-ui是一种功能强大的Java库,它使得开发人员可以更容易地为他们的RESTful API构建和维护OpenAPI文档,同时提供自定义的文档样式,帮助开发人员更轻松地与API交互。