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-openapi与spring-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交互。