Skip to content

Commit 5b31d4c

Browse files
authored
Merge pull request #548 from HXSecurity/beta
bump version to 1.12.0-beta1
2 parents 2115388 + 09a90e9 commit 5b31d4c

File tree

76 files changed

+4368
-440
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+4368
-440
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>dongtai-api-gather</artifactId>
7+
<groupId>io.dongtai.iast</groupId>
8+
<version>${revision}</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>dongtai-api-gather-dubbo-api</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.apache.dubbo</groupId>
17+
<artifactId>dubbo</artifactId>
18+
<!-- 不要修改这个依赖版本,如果必须改动需要保证在 [2.7.13, 3.0.0) 区间 -->
19+
<version>2.7.21</version>
20+
<scope>provided</scope>
21+
</dependency>
22+
<dependency>
23+
<groupId>com.alibaba</groupId>
24+
<artifactId>dubbo</artifactId>
25+
<version>2.6.12</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
29+
<dependency>
30+
<groupId>io.dongtai.iast</groupId>
31+
<artifactId>dongtai-api-gather-openapi</artifactId>
32+
<version>${project.version}</version>
33+
<scope>provided</scope>
34+
</dependency>
35+
<dependency>
36+
<groupId>io.dongtai.iast</groupId>
37+
<artifactId>dongtai-log</artifactId>
38+
<version>${project.version}</version>
39+
<scope>provided</scope>
40+
</dependency>
41+
</dependencies>
42+
43+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package io.dongtai.iast.api.gather.dubbo.convertor;
2+
3+
import io.dongtai.iast.api.openapi.convertor.OpenApiSchemaConvertorManager;
4+
import io.dongtai.iast.api.openapi.domain.MediaType;
5+
import io.dongtai.iast.api.openapi.domain.Operation;
6+
import io.dongtai.iast.api.openapi.domain.Parameter;
7+
import io.dongtai.iast.api.openapi.domain.Response;
8+
import io.dongtai.log.DongTaiLog;
9+
10+
import java.lang.reflect.Method;
11+
import java.util.*;
12+
13+
/**
14+
* 用于把Dubbo的Service的方法转为Open API的Operation结构
15+
*
16+
* @author CC11001100
17+
* @since v1.12.0
18+
*/
19+
public class MethodConvertor {
20+
21+
private OpenApiSchemaConvertorManager manager;
22+
private Method reflectionMethod;
23+
24+
/**
25+
* @param manager
26+
* @param reflectionMethod 要转换的Method,一个Method对应着一个Operation
27+
*/
28+
public MethodConvertor(OpenApiSchemaConvertorManager manager, Method reflectionMethod) {
29+
this.manager = manager;
30+
this.reflectionMethod = reflectionMethod;
31+
}
32+
33+
public Operation convert() {
34+
Operation o = new Operation();
35+
36+
try {
37+
o.mergeParameters(this.parseParameters());
38+
} catch (Throwable e) {
39+
DongTaiLog.debug("MethodConvertor.convert parseParameters exception", e);
40+
}
41+
42+
try {
43+
o.setResponses(this.parseResponse());
44+
} catch (Throwable e) {
45+
DongTaiLog.debug("MethodConvertor.convert parseResponse exception", e);
46+
}
47+
48+
// 设置这两个字段
49+
o.setOperationId(UUID.randomUUID().toString());
50+
// 把类名设置为标签
51+
o.setTags(Collections.singletonList(reflectionMethod.getDeclaringClass().getName()));
52+
53+
return o;
54+
}
55+
56+
/**
57+
* 把Dubbo的Service的方法返回值转换为Open API的Response
58+
*
59+
* @return
60+
*/
61+
private Map<String, Response> parseResponse() {
62+
63+
Class<?> returnType = this.reflectionMethod.getReturnType();
64+
// 这里需要注意,可能会有返回值为空的情况,这种情况就认为是没有响应值
65+
if (Void.TYPE == returnType) {
66+
return null;
67+
}
68+
69+
// 把函数的返回值对应到HTTP的响应体上
70+
Response r = new Response();
71+
Map<String, MediaType> contentMap = new HashMap<>();
72+
MediaType mediaType = new MediaType();
73+
mediaType.setSchema(this.manager.convertClass(returnType));
74+
contentMap.put(MediaType.APPLICATION_JSON, mediaType);
75+
r.setContent(contentMap);
76+
77+
// 这里只处理正常返回的情况,认为是200的情况,至于throws抛出异常500的情况就不再处理了
78+
Map<String, Response> responseMap = new HashMap<>();
79+
r.setDescription(Response.MSG_OK);
80+
responseMap.put(Response.CODE_OK, r);
81+
82+
return responseMap;
83+
}
84+
85+
/**
86+
* 解析Method上的参数为OpenAPI的Parameter
87+
*
88+
* @return
89+
*/
90+
private List<Parameter> parseParameters() {
91+
java.lang.reflect.Parameter[] reflectionParameterArray = this.reflectionMethod.getParameters();
92+
if (reflectionParameterArray == null || reflectionParameterArray.length == 0) {
93+
return Collections.emptyList();
94+
}
95+
List<Parameter> parameterList = new ArrayList<>();
96+
for (java.lang.reflect.Parameter reflectionParameter : reflectionParameterArray) {
97+
try {
98+
Parameter convert = new ParameterConvertor(this.manager, reflectionParameter).convert();
99+
if (convert != null) {
100+
parameterList.add(convert);
101+
}
102+
} catch (Throwable e) {
103+
DongTaiLog.debug("MethodConvertor.parseParameters ParameterConvertor exception", e);
104+
}
105+
}
106+
return parameterList;
107+
}
108+
109+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.dongtai.iast.api.gather.dubbo.convertor;
2+
3+
import io.dongtai.iast.api.openapi.convertor.OpenApiSchemaConvertorManager;
4+
import io.dongtai.iast.api.openapi.domain.Parameter;
5+
import io.dongtai.iast.api.openapi.domain.ParameterIn;
6+
import io.dongtai.iast.api.openapi.domain.Schema;
7+
8+
/**
9+
* 方法参数级别的转换,把Dubbo的Service上的Method的Parameter转为Open API的Parameter的格式
10+
*
11+
* @author CC11001100
12+
* @since v1.12.0
13+
*/
14+
public class ParameterConvertor {
15+
16+
private final OpenApiSchemaConvertorManager manager;
17+
private final java.lang.reflect.Parameter reflectionParameter;
18+
19+
/**
20+
* @param manager
21+
* @param reflectionParameter 要转换的方法参数
22+
*/
23+
public ParameterConvertor(OpenApiSchemaConvertorManager manager, java.lang.reflect.Parameter reflectionParameter) {
24+
this.manager = manager;
25+
this.reflectionParameter = reflectionParameter;
26+
}
27+
28+
public Parameter convert() {
29+
30+
Parameter openApiParameter = new Parameter();
31+
32+
// 2023-6-25 18:23:17 以后得空的时候也许可以把这里优化一下,用asm拿到真正的参数名字,这样前端页面上用户看着心情会好一些
33+
openApiParameter.setName(reflectionParameter.getName());
34+
35+
// 洞态开发人员内部约定:dubbo的参数固定认为是放在query上的,同时是必传的
36+
openApiParameter.setIn(ParameterIn.Query);
37+
openApiParameter.setRequired(true);
38+
39+
// 参数的类型转为Open API的类型,如果有涉及到复合类型的话存储到Open API的组件库中
40+
Schema schema = this.manager.convertClass(this.reflectionParameter.getType());
41+
openApiParameter.setSchema(schema);
42+
43+
return openApiParameter;
44+
}
45+
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package io.dongtai.iast.api.gather.dubbo.convertor;
2+
3+
import io.dongtai.iast.api.openapi.convertor.OpenApiSchemaConvertorManager;
4+
import io.dongtai.iast.api.openapi.domain.Operation;
5+
import io.dongtai.iast.api.openapi.domain.Path;
6+
import io.dongtai.log.DongTaiLog;
7+
8+
import java.lang.reflect.Method;
9+
import java.lang.reflect.Parameter;
10+
import java.util.*;
11+
12+
/**
13+
* 类级别的转换,将dubbo的Service接口转换为open api的格式
14+
*
15+
* @author CC11001100
16+
* @since v1.12.0
17+
*/
18+
public class ServiceConvertor {
19+
20+
private OpenApiSchemaConvertorManager manager;
21+
private Class interfaceClass;
22+
23+
public ServiceConvertor(OpenApiSchemaConvertorManager manager, Class interfaceClass) {
24+
this.manager = manager;
25+
this.interfaceClass = interfaceClass;
26+
}
27+
28+
public Map<String, Path> convert() {
29+
Map<String, Path> pathMap = new HashMap<>();
30+
for (Method parseServiceMethod : this.parseServiceMethods()) {
31+
try {
32+
Operation convert = new MethodConvertor(this.manager, parseServiceMethod).convert();
33+
Path path = new Path();
34+
path.setDubbo(convert);
35+
pathMap.put(this.buildSign(parseServiceMethod), path);
36+
} catch (Throwable e) {
37+
DongTaiLog.debug("ServiceConvertor.convert exception", e);
38+
}
39+
}
40+
return pathMap;
41+
}
42+
43+
/**
44+
* 解析Service上提供的接口
45+
*
46+
* @return
47+
*/
48+
private List<Method> parseServiceMethods() {
49+
List<Method> methodList = new ArrayList<>();
50+
Set<String> distinctSet = new HashSet<>();
51+
Queue<Class> needProcessClassQueue = new LinkedList<>();
52+
needProcessClassQueue.add(this.interfaceClass);
53+
while (!needProcessClassQueue.isEmpty()) {
54+
Class poll = needProcessClassQueue.poll();
55+
56+
// 收集当前类上的方法
57+
Method[] declaredMethods = poll.getDeclaredMethods();
58+
for (Method declaredMethod : declaredMethods) {
59+
String s = this.buildSign(declaredMethod);
60+
if (distinctSet.contains(s)) {
61+
continue;
62+
}
63+
distinctSet.add(s);
64+
methodList.add(declaredMethod);
65+
}
66+
67+
// 收集父接口,以便等下处理父接口上的方法
68+
needProcessClassQueue.addAll(Arrays.asList(poll.getInterfaces()));
69+
}
70+
71+
return methodList;
72+
}
73+
74+
/**
75+
* 方法的签名需要统一,签名的格式与dubbo流量采集那里保持一致,在server端要靠这个作为path把它们关联到一起
76+
*
77+
* @param method
78+
* @return Example: /app.iast.common.dubbo.vul.VulService/runtimeExec(java.lang.String,java.lang.StringBuilder,byte[])
79+
*/
80+
private String buildSign(Method method) {
81+
StringBuilder sign = new StringBuilder();
82+
sign.append("/").append(method.getDeclaringClass().getName()).append("/").append(method.getName()).append("(");
83+
Parameter[] parameters = method.getParameters();
84+
if (parameters != null && parameters.length != 0) {
85+
for (int i = 0; i < parameters.length; i++) {
86+
sign.append(parameters[i].getType().getCanonicalName());
87+
if (i + 1 < parameters.length) {
88+
sign.append(",");
89+
}
90+
}
91+
}
92+
return sign.append(")").toString();
93+
}
94+
95+
}

0 commit comments

Comments
 (0)