diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/filter/SessionFilter.java b/framework/gateway/src/main/java/io/metersphere/gateway/filter/SessionFilter.java index 844c3b7b9c..f9389e4ff7 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/filter/SessionFilter.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/filter/SessionFilter.java @@ -21,7 +21,7 @@ public class SessionFilter implements WebFilter { private static final String[] TO_SUB_SERVICE = new String[]{"/license", "/system", "/resource", "/sso/callback/logout", "/sso/callback/cas/logout"}; private static final String PERFORMANCE_DOWNLOAD_PREFIX = "/jmeter/"; private static final String API_DOWNLOAD_PREFIX = "/api/jmeter/"; - private static final String TRACK_IMAGE_PREFIX = "/resource/md/get/url"; + private static final String TRACK_IMAGE_PREFIX = "/resource/md/get/path"; @Resource private DiscoveryClient discoveryClient; diff --git a/framework/sdk-parent/xpack-interface/src/main/java/io/metersphere/xpack/track/issue/IssuesPlatform.java b/framework/sdk-parent/xpack-interface/src/main/java/io/metersphere/xpack/track/issue/IssuesPlatform.java index a4babfa757..8ec415e82c 100644 --- a/framework/sdk-parent/xpack-interface/src/main/java/io/metersphere/xpack/track/issue/IssuesPlatform.java +++ b/framework/sdk-parent/xpack-interface/src/main/java/io/metersphere/xpack/track/issue/IssuesPlatform.java @@ -106,10 +106,10 @@ public interface IssuesPlatform { /** * Get请求的代理 - * @param url + * @param path * @return */ - ResponseEntity proxyForGet(String url, Class responseEntityClazz); + ResponseEntity proxyForGet(String path, Class responseEntityClazz); /** * 同步MS缺陷附件到第三方平台 diff --git a/pom.xml b/pom.xml index 0475cd5ccb..71171b25dd 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 2021.0.5 5.7.5 2.7.17 - 1.0.0 + 1.1.0 7.15.0 1.10.0 7.4.1.jre8 diff --git a/test-track/backend/src/main/java/io/metersphere/controller/IssueProxyResourceController.java b/test-track/backend/src/main/java/io/metersphere/controller/IssueProxyResourceController.java index b02e5eb1fe..a35f8485fa 100644 --- a/test-track/backend/src/main/java/io/metersphere/controller/IssueProxyResourceController.java +++ b/test-track/backend/src/main/java/io/metersphere/controller/IssueProxyResourceController.java @@ -15,9 +15,10 @@ public class IssueProxyResourceController { @Resource IssueProxyResourceService issueProxyResourceService; - @GetMapping(value = "/md/get/url") - public ResponseEntity getFileByUrl(@RequestParam ("url") String url, @RequestParam (value = "platform", required = false) String platform, - @RequestParam (value = "workspace_id", required = false) String workspaceId) { - return issueProxyResourceService.getMdImageByUrl(url, platform, workspaceId); + @GetMapping(value = "/md/get/path") + public ResponseEntity getFileByPath(@RequestParam ("path") String path, + @RequestParam (value = "platform") String platform, + @RequestParam (value = "workspaceId") String workspaceId) { + return issueProxyResourceService.getMdImageByPath(path, platform, workspaceId); } } diff --git a/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java b/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java index 902308d2b2..8c9bd9f0fb 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java +++ b/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java @@ -696,8 +696,6 @@ public class IssuesService { item.setCaseCount(caseIdSet.size()); }); buildCustomField(issues); - //处理MD图片链接内容 - handleJiraIssueMdUrl(request.getWorkspaceId(), request.getProjectId(), issues); return issues; } @@ -788,35 +786,6 @@ public class IssuesService { } - private void handleJiraIssueMdUrl(String workPlaceId, String projectId, List issues) { - issues.forEach(issue -> { - if (StringUtils.isNotEmpty(issue.getDescription()) && issue.getDescription().contains("platform=Jira&")) { - issue.setDescription(replaceJiraMdUrlParam(issue.getDescription(), workPlaceId, projectId)); - } - if (StringUtils.isNotEmpty(issue.getCustomFields()) && issue.getCustomFields().contains("platform=Jira&")) { - issue.setCustomFields(replaceJiraMdUrlParam(issue.getCustomFields(), workPlaceId, projectId)); - } - if (CollectionUtils.isNotEmpty(issue.getFields())) { - issue.getFields().forEach(field -> { - if (StringUtils.isNotEmpty(field.getTextValue()) && field.getTextValue().contains("platform=Jira&")) { - field.setTextValue(replaceJiraMdUrlParam(field.getTextValue(), workPlaceId, projectId)); - } - if (StringUtils.isNotEmpty(field.getValue()) && field.getValue().contains("platform=Jira&")) { - field.setValue(replaceJiraMdUrlParam(field.getValue(), workPlaceId, projectId)); - } - }); - } - }); - } - - private String replaceJiraMdUrlParam(String url, String workspaceId, String projectId) { - if (url.contains("&workspace_id=")) { - return url; - } - return url.replaceAll("platform=Jira&", - "platform=Jira&workspace_id=" + workspaceId + "&"); - } - private Map> getCommentMap(List issues) { List issueIds = issues.stream().map(IssuesDao::getId).collect(Collectors.toList()); List comments = extIssueCommentMapper.getCommentsByIssueIds(issueIds); diff --git a/test-track/backend/src/main/java/io/metersphere/service/PlatformPluginService.java b/test-track/backend/src/main/java/io/metersphere/service/PlatformPluginService.java index a2340bcdff..00af2a67e1 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/PlatformPluginService.java +++ b/test-track/backend/src/main/java/io/metersphere/service/PlatformPluginService.java @@ -88,6 +88,7 @@ public class PlatformPluginService { ServiceIntegration serviceIntegration = baseIntegrationService.get(integrationRequest); PlatformRequest pluginRequest = new PlatformRequest(); + pluginRequest.setWorkspaceId(workspaceId); pluginRequest.setIntegrationConfig(serviceIntegration.getConfiguration()); Platform platform = getPluginManager().getPlatformByKey(platformKey, pluginRequest); if (platform == null) { diff --git a/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoClient.java b/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoClient.java index 230d7cd4e7..8a00b39e72 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoClient.java +++ b/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoClient.java @@ -4,7 +4,6 @@ import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.JSON; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.UnicodeConvertUtils; -import io.metersphere.i18n.Translator; import io.metersphere.service.issue.domain.zentao.*; import org.apache.commons.lang3.StringUtils; import org.springframework.core.io.FileSystemResource; @@ -13,6 +12,8 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Map; public abstract class ZentaoClient extends BaseClient { @@ -244,4 +245,19 @@ public abstract class ZentaoClient extends BaseClient { null, byte[].class, fileId, sessionId); return response.getBody(); } + + public ResponseEntity proxyForGet(String path, Class responseEntityClazz) { + im.metersphere.plugin.utils.LogUtil.info("zentao proxyForGet: " + path); + String url = this.ENDPOINT + path; + try { + if (!StringUtils.containsAny(new URI(url).getPath(), "/index.php", "/file-read-")) { + // 只允许访问图片 + MSException.throwException("illegal path"); + } + } catch (URISyntaxException e) { + LogUtil.error(e); + MSException.throwException("illegal path"); + } + return restTemplate.exchange(url, HttpMethod.GET, null, responseEntityClazz); + } } diff --git a/test-track/backend/src/main/java/io/metersphere/service/issue/platform/AbstractIssuePlatform.java b/test-track/backend/src/main/java/io/metersphere/service/issue/platform/AbstractIssuePlatform.java index 340cc88250..95ceed3f22 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/issue/platform/AbstractIssuePlatform.java +++ b/test-track/backend/src/main/java/io/metersphere/service/issue/platform/AbstractIssuePlatform.java @@ -6,7 +6,6 @@ import io.metersphere.base.mapper.IssuesMapper; import io.metersphere.base.mapper.TestCaseIssuesMapper; import io.metersphere.base.mapper.ext.ExtIssuesMapper; import io.metersphere.commons.constants.CustomFieldType; -import io.metersphere.commons.constants.IssueRefType; import io.metersphere.commons.constants.IssuesStatus; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.*; @@ -32,6 +31,7 @@ import org.springframework.util.MultiValueMap; import java.io.File; import java.net.URLDecoder; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Function; @@ -65,6 +65,8 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform { protected AttachmentModuleRelationMapper attachmentModuleRelationMapper; protected BaseProjectService baseProjectService; + public static final String PROXY_PATH = "/resource/md/get/path?platform=%s&workspaceId=%s&path=%s"; + public String getKey() { return key; } @@ -114,6 +116,10 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform { return integration.getConfiguration(); } + protected String getProxyPath(String path) { + return String.format(PROXY_PATH, this.key, this.workspaceId, URLEncoder.encode(path, StandardCharsets.UTF_8)); + } + protected HttpHeaders auth(String apiUser, String password) { String authKey = EncryptUtils.base64Encoding(apiUser + ":" + password); HttpHeaders headers = new HttpHeaders(); @@ -333,7 +339,7 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform { while (matcher.find()) { try { String path = matcher.group(2); - if (!path.contains("/resource/md/get/url")) { + if (!path.contains("/resource/md/get/url") && !path.contains("/resource/md/get/path")) { if (path.contains("/resource/md/get/")) { // 兼容旧数据 String name = path.substring(path.indexOf("/resource/md/get/") + 17); files.add(new File(FileUtils.MD_IMAGE_DIR + "/" + name)); diff --git a/test-track/backend/src/main/java/io/metersphere/service/issue/platform/ZentaoPlatform.java b/test-track/backend/src/main/java/io/metersphere/service/issue/platform/ZentaoPlatform.java index 857b2d67e7..c93fc8f7e6 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/issue/platform/ZentaoPlatform.java +++ b/test-track/backend/src/main/java/io/metersphere/service/issue/platform/ZentaoPlatform.java @@ -492,7 +492,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform { while (matcher.find()) { // get file name String originSubUrl = matcher.group(1); - if (originSubUrl.contains("/url?url=")) { + if (originSubUrl.contains("/url?url=") || originSubUrl.contains("/path?")) { String path = URLDecoder.decode(originSubUrl, StandardCharsets.UTF_8); String fileName; if (path.indexOf("fileID") > 0) { @@ -565,15 +565,17 @@ public class ZentaoPlatform extends AbstractIssuePlatform { } } else { name = name.replaceAll("&", "&"); - try { - URI uri = new URI(zentaoClient.getBaseUrl()); - path = uri.getScheme() + "://" + uri.getHost() + path.replaceAll("&", "&"); - } catch (URISyntaxException e) { - path = zentaoClient.getBaseUrl() + path.replaceAll("&", "&"); - LogUtil.error(e); + path = path.replaceAll("&", "&"); + } + StringBuilder stringBuilder = new StringBuilder(); + for (String item : path.split("&")) { + // 去掉多余的参数 + if (!StringUtils.containsAny(item, "platform", "workspaceId")) { + stringBuilder.append(item); + stringBuilder.append("&"); } } - path = "/resource/md/get/url?url=" + URLEncoder.encode(path, StandardCharsets.UTF_8); + path = getProxyPath(stringBuilder.toString()); } // 图片与描述信息之间需换行,否则无法预览图片 result = "\n\n![" + name + "](" + path + ")"; @@ -682,4 +684,9 @@ public class ZentaoPlatform extends AbstractIssuePlatform { } return platformStatusDTOS; } + + @Override + public ResponseEntity proxyForGet(String path, Class responseEntityClazz) { + return zentaoClient.proxyForGet(path, responseEntityClazz); + } } diff --git a/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java b/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java index f50964102a..3e74ee78e7 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java +++ b/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java @@ -1,10 +1,10 @@ package io.metersphere.service.wapper; -import io.metersphere.commons.exception.MSException; -import io.metersphere.i18n.Translator; +import io.metersphere.commons.constants.IssuesManagePlatform; import io.metersphere.service.PlatformPluginService; +import io.metersphere.service.issue.platform.IssueFactory; +import io.metersphere.xpack.track.dto.request.IssuesRequest; import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,19 +25,20 @@ public class IssueProxyResourceService { * http 代理 * 如果当前访问地址是 https,直接访问 http 的图片资源 * 由于浏览器的安全机制,http 会被转成 https - * @param url + * @param path * @param platform * @return */ - public ResponseEntity getMdImageByUrl(String url, String platform, String workspaceId) { - if (url.contains("md/get/url")) { - MSException.throwException(Translator.get("invalid_parameter")); - } - if (StringUtils.isNotBlank(platform)) { - return platformPluginService.getPlatform(platform, workspaceId) - .proxyForGet(url, byte[].class); + public ResponseEntity getMdImageByPath(String path, String platform, String workspaceId) { + if (StringUtils.equals(IssuesManagePlatform.Zentao.name(), platform)) { + IssuesRequest issuesRequest = new IssuesRequest(); + issuesRequest.setWorkspaceId(workspaceId); + return IssueFactory.createPlatform(platform, issuesRequest) + .proxyForGet(path, byte[].class); + } else { + return platformPluginService.getPlatform(platform, workspaceId) + .proxyForGet(path, byte[].class); } - return restTemplate.exchange(url, HttpMethod.GET, null, byte[].class); } }