From 26f513d2a4d6949beabc95565bdbaa64b95542bf Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Fri, 21 Oct 2022 11:00:31 +0800 Subject: [PATCH 1/7] =?UTF-8?q?fix(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA):?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92=E6=8A=A5=E5=91=8A-?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=94=A8=E4=BE=8B=E5=88=97=E8=A1=A8-?= =?UTF-8?q?=E8=B4=A3=E4=BB=BB=E4=BA=BA=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --bug=1018361 --user=陈建星 【测试跟踪】测试计划-报告统计-功能用例统计分析-所有用例-责任人为空 https://www.tapd.cn/55049933/s/1270626 --- .../metersphere/plan/service/TestPlanTestCaseService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanTestCaseService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanTestCaseService.java index 17509421ef..b04cc1e052 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanTestCaseService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanTestCaseService.java @@ -520,8 +520,10 @@ public class TestPlanTestCaseService { if (CollectionUtils.isNotEmpty(cases)) { Map projectMap = ServiceUtils.getProjectMap( cases.stream().map(TestPlanCaseDTO::getProjectId).collect(Collectors.toList())); - Map userNameMap = ServiceUtils.getUserNameMap( - cases.stream().map(TestPlanCaseDTO::getExecutor).collect(Collectors.toList())); + List userIds = new ArrayList(); + userIds.addAll(cases.stream().map(TestPlanCaseDTO::getExecutor).collect(Collectors.toList())); + userIds.addAll(cases.stream().map(TestPlanCaseDTO::getMaintainer).collect(Collectors.toList())); + Map userNameMap = ServiceUtils.getUserNameMap(userIds); cases.forEach(item -> { if (projectMap.containsKey(item.getProjectId())) { item.setProjectName(projectMap.get(item.getProjectId()).getName()); From 1cb9ce521fdb95c653081ab2a767f2bfb57e97bf Mon Sep 17 00:00:00 2001 From: song-cc-rock Date: Fri, 21 Oct 2022 10:47:00 +0800 Subject: [PATCH 2/7] =?UTF-8?q?fix(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA):?= =?UTF-8?q?=20=E5=90=8C=E6=AD=A5=E5=88=B0=E7=A6=85=E9=81=93=E7=BC=BA?= =?UTF-8?q?=E9=99=B7=E5=9B=BE=E7=89=87=E6=97=A0=E6=B3=95=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --bug=1018569 --user=宋昌昌 【测试跟踪】同步到禅道的缺陷图片无法显示 https://www.tapd.cn/55049933/s/1270622 --- .../metersphere/service/issue/client/ZentaoGetClient.java | 6 ++++-- .../service/issue/client/ZentaoPathInfoClient.java | 2 +- .../service/issue/platform/ZentaoPlatform.java | 8 +++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoGetClient.java b/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoGetClient.java index 8db2be92e8..e05e2b7482 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoGetClient.java +++ b/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoGetClient.java @@ -16,14 +16,16 @@ public class ZentaoGetClient extends ZentaoClient { private static final String STORY_GET="&module=story&methodName=getProductStories¶ms=productID={key}&t=json&zentaosid="; private static final String USER_GET="&module=user&methodName=getList&t=json&zentaosid="; private static final String BUILDS_GET="&module=build&methodName=getProductBuildPairs&productID={0}&zentaosid={1}"; - private static final String FILE_UPLOAD="&module=file&methodName=saveUpload¶ms=objectType={1},objectID={2},zentaosid={3}"; + private static final String FILE_UPLOAD="&module=file&methodName=saveUpload¶ms=objectType=bug&zentaosid={1}"; private static final String FILE_DELETE="/?m=file&f=delete&t=json&fileID={1}&confirm=yes&zentaosid={2}"; private static final String FILE_DOWNLOAD="/?m=file&f=download&t=json&fileID={1}&mouse=click&zentaosid={2}"; private static final String CREATE_META_DATA="?m=bug&f=create&productID={0}&t=json&zentaosid={1}"; private static final String REPLACE_IMG_URL=""; private static final Pattern IMG_PATTERN = Pattern.compile("m=file&f=read&fileID=(.*?)\"/>"); private static final String PRODUCT_GET = "&module=product&methodName=getById¶ms=productID={0}&zentaosid={1}"; - // 注意 recTotal={1}&recPerPage={2}&pageID={3} 顺序不能调换,有点恶心 + /** + * 注意 recTotal={1}&recPerPage={2}&pageID={3} 顺序不能调换,有点恶心 + */ private static final String BUG_LIST_URL = "/?m=bug&f=browse&productID={0}&branch=&browseType=all¶m=0&orderBy=&recTotal={1}&recPerPage={2}&pageID={3}&t=json&zentaosid={4}"; RequestUrl request = new RequestUrl(); diff --git a/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoPathInfoClient.java b/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoPathInfoClient.java index bb5b42e1c6..b34c54e879 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoPathInfoClient.java +++ b/test-track/backend/src/main/java/io/metersphere/service/issue/client/ZentaoPathInfoClient.java @@ -16,7 +16,7 @@ public class ZentaoPathInfoClient extends ZentaoClient { private static final String USER_GET = "/api-getModel-user-getList?zentaosid="; private static final String BUILDS_GET = "/api-getModel-build-getProductBuildPairs-productID={0}?zentaosid={1}"; private static final String CREATE_META_DATA="/bug-create-{0}.json?zentaosid={1}"; - private static final String FILE_UPLOAD = "/api-getModel-file-saveUpload-objectType={1},objectID={2}?zentaosid={3}"; + private static final String FILE_UPLOAD = "/api-getModel-file-saveUpload-objectType=bug?zentaosid={1}"; private static final String FILE_DELETE = "/file-delete-{1}-.yes.json?zentaosid={2}"; private static final String FILE_DOWNLOAD="/file-download-{1}-.click.json?zentaosid={2}"; private static final String REPLACE_IMG_URL = ""; 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 218bdf1946..6ae1223f30 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 @@ -26,6 +26,8 @@ import io.metersphere.service.issue.domain.zentao.ZentaoConfig; import io.metersphere.xpack.track.dto.PlatformStatusDTO; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.FileBody; import org.apache.logging.log4j.util.Strings; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpEntity; @@ -437,16 +439,16 @@ public class ZentaoPlatform extends AbstractIssuePlatform { String session = zentaoClient.login(); HttpHeaders httpHeaders = new HttpHeaders(); MultiValueMap paramMap = new LinkedMultiValueMap<>(); - HttpEntity> requestEntity = new HttpEntity<>(paramMap, httpHeaders); paramMap.add("files", resource); + HttpEntity> requestEntity = new HttpEntity<>(paramMap, httpHeaders); RestTemplate restTemplate = new RestTemplate(); try { String fileUpload = zentaoClient.requestUrl.getFileUpload(); ResponseEntity responseEntity = restTemplate.exchange(fileUpload, HttpMethod.POST, requestEntity, - String.class, "bug", null, session); + String.class, session); String body = responseEntity.getBody(); Map obj = JSON.parseMap(body); - Map data = (Map) obj.get("data"); + Map data = (Map) JSON.parseObject(obj.get("data").toString()); Set set = data.keySet(); if (!set.isEmpty()) { id = (String) set.toArray()[0]; From f5a2b5dd146f2445057024008f9ac358d97450b1 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Fri, 21 Oct 2022 10:31:33 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA):?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92=E6=8A=A5=E5=91=8A-?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E7=BB=9F=E8=AE=A1=E7=BC=BA=E9=99=B7=E5=88=97?= =?UTF-8?q?=E8=A1=A8-=E7=8A=B6=E6=80=81=E7=AD=9B=E9=80=89=E4=B8=8D?= =?UTF-8?q?=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --bug=1018362 --user=陈建星 【测试跟踪】测试计划-报告统计-功能用例统计分析-缺陷列表-列表的平台状态和筛选框的不一致 https://www.tapd.cn/55049933/s/1270592 --- .../comonents/report/detail/component/FunctionalIssueList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-track/frontend/src/business/plan/view/comonents/report/detail/component/FunctionalIssueList.vue b/test-track/frontend/src/business/plan/view/comonents/report/detail/component/FunctionalIssueList.vue index c0c84015ef..de88955bf0 100644 --- a/test-track/frontend/src/business/plan/view/comonents/report/detail/component/FunctionalIssueList.vue +++ b/test-track/frontend/src/business/plan/view/comonents/report/detail/component/FunctionalIssueList.vue @@ -95,7 +95,7 @@ export default { if (values.indexOf(status) == -1) { statusFilter.push({ value: status, - text: ISSUE_STATUS_MAP[status] ? ISSUE_STATUS_MAP[status] : status + text: ISSUE_STATUS_MAP[status] && item.platform === 'Local' ? ISSUE_STATUS_MAP[status] : status }); } } From d8d9378c4f02122c920848d107a84a15daa880b9 Mon Sep 17 00:00:00 2001 From: CaptainB Date: Fri, 21 Oct 2022 12:01:40 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20SSO=E7=99=BB=E5=BD=95=E9=80=80?= =?UTF-8?q?=E5=87=BA=E7=9B=B8=E5=85=B3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gateway/controller/LoginController.java | 6 ++- .../gateway/controller/SSOController.java | 14 ++++--- .../gateway/service/SSOService.java | 13 ++++--- .../gateway/service/UserLoginService.java | 37 +++++++++++++------ .../frontend/src/plugins/request.js | 14 +++++-- .../sdk-parent/frontend/src/utils/index.js | 11 ++++++ .../commons/utils/SessionUtils.java | 5 ++- .../controller/LoginController.java | 2 +- .../metersphere/service/SSOLogoutService.java | 9 ++++- 9 files changed, 81 insertions(+), 30 deletions(-) diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java b/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java index c9835bcbc8..268df8f136 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/controller/LoginController.java @@ -46,10 +46,12 @@ public class LoginController { private ReactiveRedisSessionRepository reactiveRedisSessionRepository; @GetMapping(value = "/is-login") - public Mono isLogin(@RequestHeader(name = SessionConstants.HEADER_TOKEN, required = false) String sessionId) throws Exception { + public Mono isLogin(@RequestHeader(name = SessionConstants.HEADER_TOKEN, required = false) String sessionId, + @RequestHeader(name = SessionConstants.CSRF_TOKEN, required = false) String csrfToken) throws Exception { RsaKey rsaKey = RsaUtil.getRsaKey(); - if (StringUtils.isNotBlank(sessionId)) { + if (StringUtils.isNotBlank(sessionId) && StringUtils.isNotBlank(csrfToken)) { + userLoginService.validateCsrfToken(sessionId, csrfToken); return reactiveRedisSessionRepository.getSessionRedisOperations().opsForHash().get("spring:session:sessions:" + sessionId, "sessionAttr:user") .switchIfEmpty(Mono.just(rsaKey)) .map(r -> { diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java b/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java index 7da48882b9..e4f96e8a7f 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/controller/SSOController.java @@ -2,6 +2,7 @@ package io.metersphere.gateway.controller; import io.metersphere.commons.constants.OperLogConstants; import io.metersphere.commons.constants.OperLogModule; +import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.utils.CodingUtil; import io.metersphere.gateway.service.SSOService; import io.metersphere.log.annotation.MsAuditLog; @@ -13,6 +14,7 @@ import reactor.core.publisher.Mono; import javax.annotation.Resource; import java.util.Locale; +import java.util.Optional; @Controller @RequestMapping("sso") @@ -23,24 +25,24 @@ public class SSOController { @GetMapping("callback/{authId}") @MsAuditLog(module = OperLogModule.AUTH_TITLE, type = OperLogConstants.LOGIN, title = "登录") public Rendering callbackWithAuthId(@RequestParam("code") String code, @PathVariable("authId") String authId, WebSession session, Locale locale) throws Exception { - ssoService.exchangeToken(code, authId, session, locale); - return Rendering.redirectTo("/#/?_token=" + CodingUtil.base64Encoding(session.getId())) + Optional sessionUser = ssoService.exchangeToken(code, authId, session, locale); + return Rendering.redirectTo("/#/?_token=" + CodingUtil.base64Encoding(session.getId()) + "&_csrf=" + sessionUser.get().getCsrfToken()) .build(); } @GetMapping("callback") @MsAuditLog(module = OperLogModule.AUTH_TITLE, type = OperLogConstants.LOGIN, title = "登录") public Rendering callback(@RequestParam("code") String code, @RequestParam("state") String authId, WebSession session, Locale locale) throws Exception { - ssoService.exchangeToken(code, authId, session, locale); - return Rendering.redirectTo("/#/?_token=" + CodingUtil.base64Encoding(session.getId())) + Optional sessionUser = ssoService.exchangeToken(code, authId, session, locale); + return Rendering.redirectTo("/#/?_token=" + CodingUtil.base64Encoding(session.getId()) + "&_csrf=" + sessionUser.get().getCsrfToken()) .build(); } @GetMapping("/callback/cas/{authId}") @MsAuditLog(module = OperLogModule.AUTH_TITLE, type = OperLogConstants.LOGIN, title = "登录") public Rendering casCallback(@RequestParam("ticket") String ticket, @PathVariable("authId") String authId, WebSession session, Locale locale) throws Exception { - ssoService.serviceValidate(ticket, authId, session, locale); - return Rendering.redirectTo("/#/?_token=" + CodingUtil.base64Encoding(session.getId())) + Optional sessionUser = ssoService.serviceValidate(ticket, authId, session, locale); + return Rendering.redirectTo("/#/?_token=" + CodingUtil.base64Encoding(session.getId()) + "&_csrf=" + sessionUser.get().getCsrfToken()) .build(); } diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/service/SSOService.java b/framework/gateway/src/main/java/io/metersphere/gateway/service/SSOService.java index 6a14cb2f31..e1243f18ed 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/service/SSOService.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/service/SSOService.java @@ -2,7 +2,6 @@ package io.metersphere.gateway.service; import io.metersphere.base.domain.AuthSource; import io.metersphere.base.domain.User; -import io.metersphere.commons.constants.UserSource; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.utils.CodingUtil; @@ -61,7 +60,7 @@ public class SSOService { @Resource private UserLoginService userLoginService; - public void exchangeToken(String code, String authId, WebSession session, Locale locale) throws Exception { + public Optional exchangeToken(String code, String authId, WebSession session, Locale locale) throws Exception { AuthSource authSource = authSourceService.getAuthSource(authId); Map config = JSON.parseObject(authSource.getConfiguration(), Map.class); String tokenUrl = (String) config.get("tokenUrl"); @@ -92,7 +91,7 @@ public class SSOService { MSException.throwException(content); } - doOICDLogin(authSource, accessToken, session, locale); + return doOICDLogin(authSource, accessToken, session, locale); } private RestTemplate getRestTemplateIgnoreSSL() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException { @@ -118,7 +117,7 @@ public class SSOService { return new RestTemplate(requestFactory); } - private void doOICDLogin(AuthSource authSource, String accessToken, WebSession session, Locale locale) throws Exception { + private Optional doOICDLogin(AuthSource authSource, String accessToken, WebSession session, Locale locale) throws Exception { Map config = JSON.parseObject(authSource.getConfiguration(), Map.class); String userInfoUrl = (String) config.get("userInfoUrl"); HttpHeaders headers = new HttpHeaders(); @@ -157,12 +156,13 @@ public class SSOService { session.getAttributes().put("authenticate", authSource.getType()); session.getAttributes().put("authId", authSource.getId()); session.getAttributes().put("user", userOptional.get()); + return userOptional; } /** * cas callback */ - public void serviceValidate(String ticket, String authId, WebSession session, Locale locale) throws Exception { + public Optional serviceValidate(String ticket, String authId, WebSession session, Locale locale) throws Exception { AuthSource authSource = authSourceService.getAuthSource(authId); Map config = JSON.parseObject(authSource.getConfiguration(), Map.class); String redirectUrl = ((String) config.get("redirectUrl")).replace("${authId}", authId); @@ -196,9 +196,12 @@ public class SSOService { session.getAttributes().put("authenticate", authSource.getType()); session.getAttributes().put("authId", authSource.getId()); session.getAttributes().put("user", userOptional.get()); + session.getAttributes().put("casTicket", ticket); // 记录cas对应关系 Long timeout = env.getProperty("spring.session.timeout", Long.class); stringRedisTemplate.opsForValue().set(ticket, name, timeout, TimeUnit.SECONDS); + + return userOptional; } public void kickOutUser(String logoutToken) { diff --git a/framework/gateway/src/main/java/io/metersphere/gateway/service/UserLoginService.java b/framework/gateway/src/main/java/io/metersphere/gateway/service/UserLoginService.java index 330b4e5721..3285d4217c 100644 --- a/framework/gateway/src/main/java/io/metersphere/gateway/service/UserLoginService.java +++ b/framework/gateway/src/main/java/io/metersphere/gateway/service/UserLoginService.java @@ -8,7 +8,6 @@ import io.metersphere.commons.constants.UserStatus; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.utils.CodingUtil; -import io.metersphere.commons.utils.SessionUtils; import io.metersphere.dto.GroupResourceDTO; import io.metersphere.dto.UserDTO; import io.metersphere.dto.UserGroupPermissionDTO; @@ -18,6 +17,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.stereotype.Service; import org.springframework.web.server.WebSession; @@ -55,7 +55,7 @@ public class UserLoginService { userDTO = loginLocalMode(request.getUsername(), request.getPassword()); break; } - autoSwitch(userDTO); + autoSwitch(session, userDTO); return Optional.of(SessionUser.fromUser(userDTO, session.getId())); } @@ -84,7 +84,7 @@ public class UserLoginService { return user; } - public void autoSwitch(UserDTO user) { + public void autoSwitch(WebSession session, UserDTO user) { // 用户有 last_project_id 权限 if (hasLastProjectPermission(user)) { return; @@ -94,7 +94,7 @@ public class UserLoginService { return; } // 判断其他权限 - checkNewWorkspaceAndProject(user); + checkNewWorkspaceAndProject(session, user); } private boolean hasLastProjectPermission(UserDTO user) { @@ -162,7 +162,7 @@ public class UserLoginService { return false; } - private void checkNewWorkspaceAndProject(UserDTO user) { + private void checkNewWorkspaceAndProject(WebSession session, UserDTO user) { List userGroups = user.getUserGroups(); List projectGroupIds = user.getGroups() .stream().filter(ug -> StringUtils.equals(ug.getType(), UserGroupType.PROJECT)) @@ -180,7 +180,7 @@ public class UserLoginService { .collect(Collectors.toList()); if (workspaces.size() > 0) { String wsId = workspaces.get(0).getSourceId(); - switchUserResource("workspace", wsId, user); + switchUserResource(session, "workspace", wsId, user); } else { // 用户登录之后没有项目和工作空间的权限就把值清空 user.setLastWorkspaceId(""); @@ -200,7 +200,7 @@ public class UserLoginService { } } - public void switchUserResource(String sign, String sourceId, UserDTO sessionUser) { + public void switchUserResource(WebSession session, String sign, String sourceId, UserDTO sessionUser) { // 获取最新UserDTO UserDTO user = getUserDTO(sessionUser.getId()); User newUser = new User(); @@ -217,9 +217,11 @@ public class UserLoginService { } BeanUtils.copyProperties(user, newUser); // 切换工作空间或组织之后更新 session 里的 user - SessionUtils.putUser(SessionUser.fromUser(user, SessionUtils.getSessionId())); + session.getAttributes().put("user", SessionUser.fromUser(user, session.getId())); + session.getAttributes().put(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, sessionUser.getId()); userMapper.updateByPrimaryKeySelective(newUser); } + public UserDTO getLoginUser(String userId, List list) { UserExample example = new UserExample(); example.createCriteria().andIdEqualTo(userId).andSourceIn(list); @@ -381,9 +383,6 @@ public class UserLoginService { } // 执行变更 userMapper.updateByPrimaryKeySelective(user); - if (StringUtils.equals(user.getStatus(), UserStatus.DISABLED)) { - SessionUtils.kickOutUser(user.getId()); - } } private List getProjectListByWsAndUserId(String userId, String workspaceId) { @@ -404,4 +403,20 @@ public class UserLoginService { })); return projectList; } + + + public void validateCsrfToken(String sessionId, String csrfToken) { + if (StringUtils.isBlank(csrfToken)) { + throw new RuntimeException("csrf token is empty"); + } + csrfToken = CodingUtil.aesDecrypt(csrfToken, SessionUser.secret, SessionUser.iv); + + String[] signatureArray = StringUtils.split(StringUtils.trimToNull(csrfToken), "|"); + if (signatureArray.length != 4) { + throw new RuntimeException("invalid token"); + } + if (!StringUtils.equals(sessionId, signatureArray[2])) { + throw new RuntimeException("Please check csrf token."); + } + } } diff --git a/framework/sdk-parent/frontend/src/plugins/request.js b/framework/sdk-parent/frontend/src/plugins/request.js index 46dc543fff..5a484dbca3 100644 --- a/framework/sdk-parent/frontend/src/plugins/request.js +++ b/framework/sdk-parent/frontend/src/plugins/request.js @@ -3,7 +3,7 @@ import {$error} from "./message" import {getCurrentProjectID, getCurrentWorkspaceId} from "../utils/token"; import {PROJECT_ID, TokenKey, WORKSPACE_ID} from "../utils/constants"; import packageJSON from '@/../package.json' -import {getUUID} from "../utils"; +import {getUrlParams, getUUID} from "../utils"; import {Base64} from "js-base64"; // baseURL 根据是否是独立运行修改 @@ -21,6 +21,8 @@ if (window.location.pathname.startsWith('/' + packageJSON.name)) { } } +let urlParams = getUrlParams(window.location.href); + const instance = axios.create({ baseURL, // url = base url + request url withCredentials: true, @@ -39,12 +41,18 @@ instance.interceptors.request.use( } // sso callback 过来的会有sessionId在url上 if (!config.headers['X-AUTH-TOKEN']) { - const paramsStr = window.location.href - let sessionId = paramsStr.split('_token=')[1] + let sessionId = urlParams['_token'] if (sessionId) { config.headers['X-AUTH-TOKEN'] = Base64.decode(sessionId); } } + // sso callback 过来的会有csrf在url上 + if (!config.headers['CSRF-TOKEN']) { + let csrf = urlParams['_csrf'] + if (csrf) { + config.headers['CSRF-TOKEN'] = csrf; + } + } // 包含 工作空间 项目的标识 config.headers['WORKSPACE'] = getCurrentWorkspaceId(); config.headers['PROJECT'] = getCurrentProjectID(); diff --git a/framework/sdk-parent/frontend/src/utils/index.js b/framework/sdk-parent/frontend/src/utils/index.js index dd8ba21ec4..96368943bc 100644 --- a/framework/sdk-parent/frontend/src/utils/index.js +++ b/framework/sdk-parent/frontend/src/utils/index.js @@ -328,3 +328,14 @@ function _resizeTextarea(i, size, textareaList) { export function checkMicroMode() { return sessionStorage.getItem("MICRO_MODE"); } + +export function getUrlParams(url) { + const arrSearch = url.split('?').pop().split('#').shift().split('&'); + let obj = {}; + arrSearch.forEach((item) => { + const [k, v] = item.split('='); + obj[k] = v; + return obj; + }); + return obj; +} diff --git a/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/utils/SessionUtils.java b/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/utils/SessionUtils.java index b224ef6a22..4f9a5847d5 100644 --- a/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/utils/SessionUtils.java +++ b/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/utils/SessionUtils.java @@ -59,7 +59,10 @@ public class SessionUtils { } Map users = sessionRepository.findByPrincipalName(username); if (MapUtils.isNotEmpty(users)) { - users.keySet().forEach(sessionRepository::deleteById); + users.keySet().forEach(k -> { + sessionRepository.deleteById(k); + sessionRepository.getSessionRedisOperations().delete("spring:session:sessions:" + k); + }); } } diff --git a/framework/sdk-parent/sdk/src/main/java/io/metersphere/controller/LoginController.java b/framework/sdk-parent/sdk/src/main/java/io/metersphere/controller/LoginController.java index c20978c7e8..1ef66312bd 100644 --- a/framework/sdk-parent/sdk/src/main/java/io/metersphere/controller/LoginController.java +++ b/framework/sdk-parent/sdk/src/main/java/io/metersphere/controller/LoginController.java @@ -87,7 +87,7 @@ public class LoginController { @GetMapping(value = "/signout") @MsAuditLog(module = OperLogModule.AUTH_TITLE, beforeEvent = "#msClass.getUserId(id)", type = OperLogConstants.LOGIN, title = "登出", msClass = SessionUtils.class) public ResultHolder logout() throws Exception { - ssoLogoutService.logout(); + ssoLogoutService.logout(SecurityUtils.getSubject().getSession()); SecurityUtils.getSubject().logout(); return ResultHolder.success(StringUtils.EMPTY); } diff --git a/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/SSOLogoutService.java b/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/SSOLogoutService.java index f21aff19bd..d691adbecc 100644 --- a/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/SSOLogoutService.java +++ b/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/SSOLogoutService.java @@ -8,6 +8,7 @@ import io.metersphere.commons.utils.JSON; import io.metersphere.commons.utils.SessionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -27,7 +28,7 @@ public class SSOLogoutService { /** * oidc logout */ - public void logout() throws Exception { + public void logout(Session session) throws Exception { String authId = (String) SecurityUtils.getSubject().getSession().getAttribute("authId"); AuthSource authSource = authSourceMapper.selectByPrimaryKey(authId); if (authSource != null) { @@ -38,6 +39,12 @@ public class SSOLogoutService { restTemplate.getForEntity(logoutUrl + "?id_token_hint=" + idToken, String.class); } + if (StringUtils.equals(UserSource.CAS.name(), authSource.getType())) { + String casTicket = (String) session.getAttribute("casTicket"); + if (StringUtils.isNotEmpty(casTicket)) { + stringRedisTemplate.delete(casTicket); + } + } } } From 414fe300040052743b6605554afc4dd95b216702 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Fri, 21 Oct 2022 14:32:51 +0800 Subject: [PATCH 5/7] =?UTF-8?q?fix(=E7=B3=BB=E7=BB=9F=E8=AE=BE=E7=BD=AE):?= =?UTF-8?q?=20=E7=8E=AF=E5=A2=83=E5=88=97=E8=A1=A8=E8=A1=A8=E5=A4=B4?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=A1=BA=E5=BA=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --bug=1018575 --user=李玉号 【系统设置】工作空间-环境管理-环境列表表头显示顺序优化 https://www.tapd.cn/55049933/s/1270905 --- .../src/business/workspace/environment/EnvironmentList.vue | 6 +++--- system-setting/frontend/src/i18n/lang/en-US.js | 3 ++- system-setting/frontend/src/i18n/lang/zh-CN.js | 3 ++- system-setting/frontend/src/i18n/lang/zh-TW.js | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/system-setting/frontend/src/business/workspace/environment/EnvironmentList.vue b/system-setting/frontend/src/business/workspace/environment/EnvironmentList.vue index 900f0ee7d4..7b87915013 100644 --- a/system-setting/frontend/src/business/workspace/environment/EnvironmentList.vue +++ b/system-setting/frontend/src/business/workspace/environment/EnvironmentList.vue @@ -4,7 +4,7 @@