From 2bdbcc2bcce333f2e580a5a25b78cec7a1c823b6 Mon Sep 17 00:00:00 2001 From: yaoxuwan Date: Wed, 20 Nov 2024 15:33:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81websocket=20#2494?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 支持websocket #2494 * feat: 支持websocket #2494 * feat: 支持websocket #2494 * feat: 支持websocket #2494 --- src/backend/build.gradle.kts | 1 + .../CustomMetricsPushAutoConfiguration.kt | 4 +- .../bkrepo/common/redis/RedisOperation.kt | 4 +- .../config/boot-config/build.gradle.kts | 1 + src/backend/settings.gradle.kts | 1 + .../websocket/biz-websocket/build.gradle.kts | 40 ++++++ .../websocket/config/WebSocketConfigurer.kt | 48 +++++++ .../websocket/config/WebSocketProperties.kt | 37 +++++ .../config/WebsocketConfiguration.kt | 117 ++++++++++++++++ .../WsThreadPoolTaskExeccutorConfiguration.kt | 65 +++++++++ .../websocket/constant/WebsocketKeys.kt | 34 +++++ .../controller/ClipboardController.kt | 52 +++++++ .../bkrepo/websocket/dispatch/Dispatcher.kt | 36 +++++ .../websocket/dispatch/TransferDispatch.kt | 54 ++++++++ .../dispatch/push/CopyPDUTransferPush.kt | 37 +++++ .../dispatch/push/PastePDUTransferPush.kt | 37 +++++ .../websocket/dispatch/push/TransferPush.kt | 33 +++++ .../exception/WebsocketExceptionHandler.kt | 48 +++++++ .../websocket/handler/SessionHandler.kt | 131 ++++++++++++++++++ ...SessionWebSocketHandlerDecoratorFactory.kt | 45 ++++++ .../listener/TransferPushListener.kt | 51 +++++++ .../bkrepo/websocket/pojo/fs/CopyPDU.kt | 40 ++++++ .../bkrepo/websocket/pojo/fs/PastePDU.kt | 36 +++++ .../websocket/service/ClipboardService.kt | 58 ++++++++ .../websocket/service/WebsocketService.kt | 63 +++++++++ .../bkrepo/websocket/util/HostUtils.kt | 84 +++++++++++ .../websocket/boot-websocket/build.gradle.kts | 34 +++++ .../bkrepo/websocket/WebsocketApplication.kt | 41 ++++++ .../src/main/resources/bootstrap.yml | 4 + src/backend/websocket/build.gradle.kts | 30 ++++ src/gateway/auth.conf | 6 + src/gateway/lua/auth/auth_web.lua | 6 + src/gateway/lua/auth/auth_websocket.lua | 55 ++++++++ src/gateway/lua/router_srv.lua | 2 +- src/gateway/vhosts/bkrepo.websocket.conf | 47 +++++++ .../gateway#vhosts#bkrepo.server.conf | 3 + 36 files changed, 1380 insertions(+), 5 deletions(-) create mode 100644 src/backend/websocket/biz-websocket/build.gradle.kts create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt create mode 100644 src/backend/websocket/boot-websocket/build.gradle.kts create mode 100644 src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt create mode 100644 src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml create mode 100644 src/backend/websocket/build.gradle.kts create mode 100644 src/gateway/lua/auth/auth_websocket.lua create mode 100644 src/gateway/vhosts/bkrepo.websocket.conf diff --git a/src/backend/build.gradle.kts b/src/backend/build.gradle.kts index 2813fe9475..0bd3c7fc73 100644 --- a/src/backend/build.gradle.kts +++ b/src/backend/build.gradle.kts @@ -87,6 +87,7 @@ allprojects { exclude(group = "log4j", module = "log4j") exclude(group = "org.slf4j", module = "slf4j-log4j12") exclude(group = "commons-logging", module = "commons-logging") + exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat") } tasks.withType { diff --git a/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt b/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt index 9b001532fd..4b30537e63 100644 --- a/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt +++ b/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt @@ -101,10 +101,10 @@ class CustomMetricsPushAutoConfiguration { fun customMetricsExporter( drive: PrometheusDrive, prometheusProperties: PrometheusProperties, - scheduler: ThreadPoolTaskScheduler, + taskScheduler: ThreadPoolTaskScheduler, customPushConfig: CustomPushConfig, ): CustomMetricsExporter { - return CustomMetricsExporter(customPushConfig, CollectorRegistry(), drive, prometheusProperties, scheduler) + return CustomMetricsExporter(customPushConfig, CollectorRegistry(), drive, prometheusProperties, taskScheduler) } diff --git a/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt b/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt index e851e8475b..de21b92aa1 100644 --- a/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt +++ b/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt @@ -63,8 +63,8 @@ class RedisOperation(private val redisTemplate: RedisTemplate) { } } - fun delete(key: String) { - redisTemplate.delete(key) + fun delete(key: String): Boolean { + return redisTemplate.delete(key) } fun delete(keys: Collection) { diff --git a/src/backend/config/boot-config/build.gradle.kts b/src/backend/config/boot-config/build.gradle.kts index 01bbf7507b..516184f9fb 100644 --- a/src/backend/config/boot-config/build.gradle.kts +++ b/src/backend/config/boot-config/build.gradle.kts @@ -32,4 +32,5 @@ dependencies { implementation("org.springframework.cloud:spring-cloud-config-server:3.1.6") implementation("org.springframework.cloud:spring-cloud-starter-bootstrap:3.1.6") + implementation("io.undertow:undertow-servlet") } diff --git a/src/backend/settings.gradle.kts b/src/backend/settings.gradle.kts index 23128e5dcc..e483e7aa46 100644 --- a/src/backend/settings.gradle.kts +++ b/src/backend/settings.gradle.kts @@ -93,3 +93,4 @@ includeAll(":router-controller") includeAll(":media") includeAll(":common:common-metadata") includeAll(":common:common-service") +includeAll(":websocket") diff --git a/src/backend/websocket/biz-websocket/build.gradle.kts b/src/backend/websocket/biz-websocket/build.gradle.kts new file mode 100644 index 0000000000..8e10e0a113 --- /dev/null +++ b/src/backend/websocket/biz-websocket/build.gradle.kts @@ -0,0 +1,40 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED " AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +dependencies { + api(project(":common:common-stream")) + api(project(":common:common-service")) + api(project(":common:common-artifact:artifact-service")) + implementation("org.springframework.boot:spring-boot-starter-websocket") + implementation("javax.websocket:javax.websocket-api") + implementation("io.undertow:undertow-servlet") + implementation("io.undertow:undertow-websockets-jsr") +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt new file mode 100644 index 0000000000..892cb634f9 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt @@ -0,0 +1,48 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import com.tencent.bkrepo.common.artifact.config.ArtifactConfigurerSupport +import com.tencent.bkrepo.common.artifact.pojo.RepositoryType +import com.tencent.bkrepo.common.artifact.repository.local.LocalRepository +import com.tencent.bkrepo.common.artifact.repository.remote.RemoteRepository +import com.tencent.bkrepo.common.artifact.repository.virtual.VirtualRepository +import com.tencent.bkrepo.common.security.http.core.HttpAuthSecurityCustomizer +import org.springframework.context.annotation.Configuration + +@Configuration +class WebSocketConfigurer : ArtifactConfigurerSupport() { + + override fun getRepositoryType() = RepositoryType.NONE + override fun getLocalRepository(): LocalRepository = object : LocalRepository() {} + override fun getRemoteRepository(): RemoteRepository = object : RemoteRepository() {} + override fun getVirtualRepository(): VirtualRepository = object : VirtualRepository() {} + + override fun getAuthSecurityCustomizer() = + HttpAuthSecurityCustomizer { httpAuthSecurity -> httpAuthSecurity.withPrefix("/websocket") } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt new file mode 100644 index 0000000000..79fe623d87 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt @@ -0,0 +1,37 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties("websocket") +data class WebSocketProperties( + var cacheLimit: Int = 3600, + var minThread: Int = 8, + var transfer: Boolean = false +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt new file mode 100644 index 0000000000..aced41f2e9 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt @@ -0,0 +1,117 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import com.tencent.bkrepo.common.security.http.jwt.JwtAuthProperties +import com.tencent.bkrepo.common.security.manager.AuthenticationManager +import com.tencent.bkrepo.websocket.constant.APP_ENDPOINT +import com.tencent.bkrepo.websocket.constant.DESKTOP_ENDPOINT +import com.tencent.bkrepo.websocket.constant.USER_ENDPOINT +import com.tencent.bkrepo.websocket.dispatch.push.TransferPush +import com.tencent.bkrepo.websocket.handler.SessionWebSocketHandlerDecoratorFactory +import com.tencent.bkrepo.websocket.listener.TransferPushListener +import com.tencent.bkrepo.websocket.service.WebsocketService +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.messaging.Message +import org.springframework.messaging.simp.config.ChannelRegistration +import org.springframework.messaging.simp.config.MessageBrokerRegistry +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker +import org.springframework.web.socket.config.annotation.StompEndpointRegistry +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer +import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration +import java.util.function.Consumer + +@Configuration +@EnableWebSocketMessageBroker +@EnableConfigurationProperties(WebSocketProperties::class) +class WebsocketConfiguration( + private val webSocketProperties: WebSocketProperties, + private val websocketService: WebsocketService, + private val jwtAuthProperties: JwtAuthProperties, + private val authenticationManager: AuthenticationManager, + private val taskScheduler: ThreadPoolTaskScheduler +) : WebSocketMessageBrokerConfigurer { + + override fun configureMessageBroker(config: MessageBrokerRegistry) { + config.setCacheLimit(webSocketProperties.cacheLimit) + config.enableSimpleBroker("/topic") + .setHeartbeatValue(longArrayOf(3000,3000)) + .setTaskScheduler(taskScheduler) + config.setApplicationDestinationPrefixes("/app") + } + + override fun registerStompEndpoints(registry: StompEndpointRegistry) { + registry.addEndpoint(USER_ENDPOINT, APP_ENDPOINT, DESKTOP_ENDPOINT) + .setAllowedOriginPatterns("*") + registry.addEndpoint(USER_ENDPOINT, APP_ENDPOINT, DESKTOP_ENDPOINT) + .setAllowedOriginPatterns("*") + .withSockJS() + } + + @Override + override fun configureClientInboundChannel(registration: ChannelRegistration) { + var defaultCorePoolSize = webSocketProperties.minThread + if (defaultCorePoolSize < Runtime.getRuntime().availableProcessors() * 2) { + defaultCorePoolSize = Runtime.getRuntime().availableProcessors() * 2 + } + registration.taskExecutor().corePoolSize(defaultCorePoolSize) + .maxPoolSize(defaultCorePoolSize * 2) + .keepAliveSeconds(60) + } + + @Override + override fun configureClientOutboundChannel(registration: ChannelRegistration) { + var defaultCorePoolSize = webSocketProperties.minThread + if (defaultCorePoolSize < Runtime.getRuntime().availableProcessors() * 2) { + defaultCorePoolSize = Runtime.getRuntime().availableProcessors() * 2 + } + registration.taskExecutor().corePoolSize(defaultCorePoolSize).maxPoolSize(defaultCorePoolSize * 2) + } + + override fun configureWebSocketTransport(registration: WebSocketTransportRegistration) { + registration.addDecoratorFactory(wsHandlerDecoratorFactory()) + super.configureWebSocketTransport(registration) + } + + @Bean + fun wsHandlerDecoratorFactory(): SessionWebSocketHandlerDecoratorFactory { + return SessionWebSocketHandlerDecoratorFactory( + websocketService = websocketService, + authenticationManager = authenticationManager, + jwtAuthProperties = jwtAuthProperties + ) + } + + @Bean + fun websocketTransferConsumer(transferPushListener: TransferPushListener): Consumer> { + return Consumer { transferPushListener.accept(it) } + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt new file mode 100644 index 0000000000..9ac531f7d6 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt @@ -0,0 +1,65 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration +import org.springframework.boot.task.TaskExecutorBuilder +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Lazy +import org.springframework.context.annotation.Primary +import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor + +/** + * Websocket会注册自定义的ThreadPoolTaskExecutor + * + * [org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration.clientInboundChannelExecutor] + * + * [org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration.clientOutboundChannelExecutor] + * + * [org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration.brokerChannelExecutor] + * + * 导致默认的ThreadPoolTaskExecutor不会实例化 + * + * [org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration.applicationTaskExecutor] + * + */ +@Configuration +class WsThreadPoolTaskExeccutorConfiguration { + + @Lazy + @Bean(name = [ + TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME, + AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME + ]) + @Primary + fun applicationTaskExecutor(builder: TaskExecutorBuilder): ThreadPoolTaskExecutor { + return builder.build() + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt new file mode 100644 index 0000000000..bf0769d39c --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.constant + +const val USER_ENDPOINT = "/ws/user" +const val APP_ENDPOINT = "/ws/app" +const val DESKTOP_ENDPOINT = "/ws/desktop" + +const val SESSION_ID = "sessionId" diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt new file mode 100644 index 0000000000..1f929a99e5 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt @@ -0,0 +1,52 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.controller + +import com.tencent.bkrepo.websocket.pojo.fs.CopyPDU +import com.tencent.bkrepo.websocket.pojo.fs.PastePDU +import com.tencent.bkrepo.websocket.service.ClipboardService +import org.springframework.messaging.handler.annotation.MessageMapping +import org.springframework.stereotype.Controller + +@Controller +@MessageMapping("/clipboard") +class ClipboardController( + private val clipboardService: ClipboardService +) { + + @MessageMapping("/copy") + fun copy(copyPDU: CopyPDU) { + clipboardService.copy(copyPDU) + } + + @MessageMapping("/paste") + fun paste(pastePDU: PastePDU) { + clipboardService.paste(pastePDU) + } +} + diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt new file mode 100644 index 0000000000..81c5cb5bd9 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt @@ -0,0 +1,36 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch + +/** + * 下发接口 + */ +interface Dispatcher { + + fun dispatch(data: T) +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt new file mode 100644 index 0000000000..4986de5d81 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt @@ -0,0 +1,54 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch + +import com.tencent.bkrepo.common.api.util.toJsonString +import com.tencent.bkrepo.common.stream.event.supplier.MessageSupplier +import com.tencent.bkrepo.websocket.config.WebSocketProperties +import com.tencent.bkrepo.websocket.dispatch.push.TransferPush +import org.springframework.messaging.simp.SimpMessagingTemplate +import org.springframework.stereotype.Component + +@Component +class TransferDispatch( + private val messageSupplier: MessageSupplier, + private val simpMessagingTemplate: SimpMessagingTemplate, + private val webSocketProperties: WebSocketProperties +) : Dispatcher { + override fun dispatch(data: TransferPush) { + if (webSocketProperties.transfer) { + messageSupplier.delegateToSupplier(data, topic = TOPIC) + } else { + simpMessagingTemplate.convertAndSend(data.topic, data.data.toJsonString()) + } + } + + companion object { + private const val TOPIC = "websocket-transfer-out-0" + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt new file mode 100644 index 0000000000..7ccd8c870a --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt @@ -0,0 +1,37 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch.push + +import com.tencent.bkrepo.websocket.pojo.fs.CopyPDU + +class CopyPDUTransferPush( + copyPDU: CopyPDU, +) : TransferPush( + topic = "/topic/clipboard/copy/${copyPDU.workspaceName}", + data = copyPDU +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt new file mode 100644 index 0000000000..f6da31f94b --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt @@ -0,0 +1,37 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch.push + +import com.tencent.bkrepo.websocket.pojo.fs.PastePDU + +class PastePDUTransferPush( + pastePDU: PastePDU, +) : TransferPush( + topic = "/topic/clipboard/paste/${pastePDU.workspaceName}", + data = pastePDU +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt new file mode 100644 index 0000000000..450654566f --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch.push + +open class TransferPush( + open val topic: String, + open val data: Any +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt new file mode 100644 index 0000000000..60ae6dbb17 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt @@ -0,0 +1,48 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.exception + +import com.tencent.bkrepo.common.api.exception.ErrorCodeException +import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.service.exception.AbstractExceptionHandler +import org.springframework.messaging.handler.annotation.MessageExceptionHandler +import org.springframework.web.bind.annotation.RestControllerAdvice + +@RestControllerAdvice +class WebsocketExceptionHandler : AbstractExceptionHandler() { + + @MessageExceptionHandler(ErrorCodeException::class) + fun handleException(exception: ErrorCodeException): Response { + return response(exception) + } + + @MessageExceptionHandler(Exception::class) + fun handleException(exception: Exception): Response { + return response(exception) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt new file mode 100644 index 0000000000..86e6ed35d5 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt @@ -0,0 +1,131 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.handler + +import com.tencent.bkrepo.common.api.constant.AUTH_HEADER_UID +import com.tencent.bkrepo.common.api.constant.CharPool.COLON +import com.tencent.bkrepo.common.api.constant.HttpHeaders +import com.tencent.bkrepo.common.api.constant.PLATFORM_AUTH_PREFIX +import com.tencent.bkrepo.common.api.constant.PLATFORM_KEY +import com.tencent.bkrepo.common.api.constant.USER_KEY +import com.tencent.bkrepo.common.artifact.stream.closeQuietly +import com.tencent.bkrepo.common.security.exception.AuthenticationException +import com.tencent.bkrepo.common.security.http.jwt.JwtAuthProperties +import com.tencent.bkrepo.common.security.manager.AuthenticationManager +import com.tencent.bkrepo.common.security.util.JwtUtils +import com.tencent.bkrepo.websocket.constant.APP_ENDPOINT +import com.tencent.bkrepo.websocket.constant.SESSION_ID +import com.tencent.bkrepo.websocket.constant.USER_ENDPOINT +import com.tencent.bkrepo.websocket.service.WebsocketService +import com.tencent.bkrepo.websocket.util.HostUtils +import io.jsonwebtoken.ExpiredJwtException +import io.jsonwebtoken.MalformedJwtException +import io.jsonwebtoken.UnsupportedJwtException +import io.jsonwebtoken.security.SignatureException +import org.slf4j.LoggerFactory +import org.springframework.web.socket.CloseStatus +import org.springframework.web.socket.WebSocketHandler +import org.springframework.web.socket.WebSocketSession +import org.springframework.web.socket.handler.WebSocketHandlerDecorator +import java.util.Base64 + +class SessionHandler( + delegate: WebSocketHandler, + private val websocketService: WebsocketService, + private val authenticationManager: AuthenticationManager, + jwtProperties: JwtAuthProperties +) : WebSocketHandlerDecorator(delegate) { + + private val signingKey = JwtUtils.createSigningKey(jwtProperties.secretKey) + + // 链接关闭记录去除session + override fun afterConnectionClosed(session: WebSocketSession, closeStatus: CloseStatus) { + val uri = session.uri + if (closeStatus.code != CloseStatus.NORMAL.code && closeStatus.code != CloseStatus.PROTOCOL_ERROR.code) { + logger.warn("websocket close abnormal, [$closeStatus] [${session.uri}] [${session.remoteAddress}]") + } + val sessionId = HostUtils.getRealSession(session.uri?.query) + if (sessionId.isNullOrEmpty()) { + logger.warn("connection closed can not find sessionId, $uri| ${session.remoteAddress}") + super.afterConnectionClosed(session, closeStatus) + } + websocketService.removeCacheSession(sessionId!!) + + super.afterConnectionClosed(session, closeStatus) + } + + override fun afterConnectionEstablished(session: WebSocketSession) { + val uri = session.uri + val remoteAddr = session.remoteAddress + val sessionId = HostUtils.getRealSession(uri?.query) + try { + authorization(session) + } catch (e: Exception) { + val authException = e is AuthenticationException || e is ExpiredJwtException || + e is UnsupportedJwtException || e is MalformedJwtException || + e is SignatureException || e is IllegalArgumentException + if (authException) { + logger.info("auth failed: |$sessionId| $uri | $remoteAddr | ${e.message}") + session.closeQuietly() + } else { + throw e + } + } + } + + private fun authorization(session: WebSocketSession) { + val uri = session.uri + val remoteId = session.remoteAddress + val sessionId = HostUtils.getRealSession(uri?.query) + when { + uri == null -> throw AuthenticationException("uri is null") + uri.path.startsWith(USER_ENDPOINT) -> { + val platformToken = session.handshakeHeaders[HttpHeaders.AUTHORIZATION]?.firstOrNull()?.toString() + ?.removePrefix(PLATFORM_AUTH_PREFIX) ?: throw AuthenticationException("platform credential is null") + val (accessKey, secretKey) = String(Base64.getDecoder().decode(platformToken)).split(COLON) + val appId = authenticationManager.checkPlatformAccount(accessKey, secretKey) + session.attributes[PLATFORM_KEY] = appId + session.attributes[USER_KEY] = session.handshakeHeaders[AUTH_HEADER_UID] + } + uri.path.startsWith(APP_ENDPOINT) -> { + val token = session.handshakeHeaders[HttpHeaders.AUTHORIZATION]?.firstOrNull().orEmpty() + val claims = JwtUtils.validateToken(signingKey, token).body + session.attributes[USER_KEY] = claims.subject + } + else -> throw AuthenticationException("invalid uri") + } + websocketService.addCacheSession(sessionId!!) + session.attributes[SESSION_ID] = sessionId + logger.info("connection success: |$sessionId| $uri | $remoteId | ${session.attributes[USER_KEY]} ") + super.afterConnectionEstablished(session) + } + + companion object { + private val logger = LoggerFactory.getLogger(SessionHandler::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt new file mode 100644 index 0000000000..6b1a45a695 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt @@ -0,0 +1,45 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.handler + +import com.tencent.bkrepo.common.security.http.jwt.JwtAuthProperties +import com.tencent.bkrepo.common.security.manager.AuthenticationManager +import com.tencent.bkrepo.websocket.service.WebsocketService +import org.springframework.web.socket.WebSocketHandler +import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory + +class SessionWebSocketHandlerDecoratorFactory ( + private val websocketService: WebsocketService, + private val authenticationManager: AuthenticationManager, + private val jwtAuthProperties: JwtAuthProperties, +) : WebSocketHandlerDecoratorFactory { + + override fun decorate(handler: WebSocketHandler): WebSocketHandler { + return SessionHandler(handler, websocketService, authenticationManager, jwtAuthProperties) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt new file mode 100644 index 0000000000..1a21c7f3d1 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.listener + +import com.tencent.bkrepo.common.api.util.toJsonString +import com.tencent.bkrepo.websocket.dispatch.push.TransferPush +import org.slf4j.LoggerFactory +import org.springframework.messaging.Message +import org.springframework.messaging.simp.SimpMessagingTemplate +import org.springframework.stereotype.Component + +@Component +class TransferPushListener( + private val simpMessagingTemplate: SimpMessagingTemplate +) { + + fun accept(message: Message) { + logger.debug(message.payload.toString()) + val transferPush = message.payload + simpMessagingTemplate.convertAndSend(transferPush.topic, transferPush.data.toJsonString()) + } + + companion object { + private val logger = LoggerFactory.getLogger(TransferPushListener::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt new file mode 100644 index 0000000000..01da102c98 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt @@ -0,0 +1,40 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.pojo.fs + +/** + * 复制协议数据单元 + */ +data class CopyPDU( + val projectId: String, + val userId: String, + val workspaceName: String, + val files: Map, + val timestamp: Long, + val dstPath: String? = null +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt new file mode 100644 index 0000000000..f295772852 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt @@ -0,0 +1,36 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.pojo.fs + +/** + * 粘贴协议数据单元 + */ +data class PastePDU( + val workspaceName: String, + val timestamp: Long, +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt new file mode 100644 index 0000000000..641c2b68fb --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt @@ -0,0 +1,58 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.service + +import com.tencent.bkrepo.websocket.dispatch.TransferDispatch +import com.tencent.bkrepo.websocket.dispatch.push.CopyPDUTransferPush +import com.tencent.bkrepo.websocket.dispatch.push.PastePDUTransferPush +import com.tencent.bkrepo.websocket.pojo.fs.CopyPDU +import com.tencent.bkrepo.websocket.pojo.fs.PastePDU +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service + +@Service +class ClipboardService( + private val transferDispatch: TransferDispatch +) { + + fun copy(copyPDU: CopyPDU) { + logger.info("CopyPDU: $copyPDU") + val copyPDUTransferPush = CopyPDUTransferPush(copyPDU) + transferDispatch.dispatch(copyPDUTransferPush) + } + + fun paste(pastePDU: PastePDU) { + logger.info("PastePDU: $pastePDU") + val pastePDUTransferPush = PastePDUTransferPush(pastePDU) + transferDispatch.dispatch(pastePDUTransferPush) + } + + companion object { + private val logger = LoggerFactory.getLogger(ClipboardService::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt new file mode 100644 index 0000000000..559f495445 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt @@ -0,0 +1,63 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.service + +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import java.util.Collections + +@Service +class WebsocketService { + private val cacheSessionList = Collections.synchronizedList(mutableListOf()) + + fun addCacheSession(sessionId: String) { + if (cacheSessionList.contains(sessionId)) { + logger.warn("this session[$sessionId] already in cacheSession") + return + } + cacheSessionList.add(sessionId) + } + + // 清楚实例内部缓存的session + fun removeCacheSession(sessionId: String) { + cacheSessionList.remove(sessionId) + } + + // 判断获取到的session是否由该实例持有 + fun isCacheSession(sessionId: String): Boolean { + if (cacheSessionList.contains(sessionId)) { + logger.debug("sessionId[$sessionId] is in this host") + return true + } + return false + } + + companion object { + private val logger = LoggerFactory.getLogger(WebsocketService::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt new file mode 100644 index 0000000000..19a64fdc90 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt @@ -0,0 +1,84 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.util + +import org.slf4j.LoggerFactory +import java.net.DatagramSocket +import java.net.InetAddress +import java.net.URL + +object HostUtils { + + fun getHostIp(gateway: String?): String { + try { + val localHost = InetAddress.getLocalHost() + return if (localHost.isLoopbackAddress) { + getFromUDP(gateway) ?: DEFAULT_IP + } else { + localHost.hostAddress + } + } catch (e: Throwable) { + logger.warn("Fail to get local host ip", e) + try { + return getFromUDP(gateway) ?: DEFAULT_IP + } catch (t: Throwable) { + logger.warn("Fail to use socket to get the localhost host") + } + } + return DEFAULT_IP + } + + private fun getFromUDP(gateway: String?): String? { + if (gateway.isNullOrBlank()) { + return null + } + + val gatewayHost = try { + val url = URL(gateway) + url.host + } catch (t: Throwable) { + logger.warn("Fail to get the gateway host", t) + return null + } + + DatagramSocket().use { socket -> + socket.connect(InetAddress.getByName(gatewayHost), 10002) + return socket.localAddress.hostAddress + } + } + + fun getRealSession(query: String?): String? { + if (query.isNullOrEmpty()) { + return null + } + return query.substringAfter("sessionId=").substringBefore("&t=") + } + + private const val DEFAULT_IP = "127.0.0.1" + private val logger = LoggerFactory.getLogger(javaClass) +} diff --git a/src/backend/websocket/boot-websocket/build.gradle.kts b/src/backend/websocket/boot-websocket/build.gradle.kts new file mode 100644 index 0000000000..49bd2145ce --- /dev/null +++ b/src/backend/websocket/boot-websocket/build.gradle.kts @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED " AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +dependencies { + implementation(project(":websocket:biz-websocket")) +} diff --git a/src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt b/src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt new file mode 100644 index 0000000000..5a71325d24 --- /dev/null +++ b/src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt @@ -0,0 +1,41 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket + +import com.tencent.bkrepo.common.service.condition.MicroService +import org.springframework.boot.runApplication + +/** + * Websocket微服务启动类 + */ +@MicroService +class WebsocketApplication + +fun main(args: Array) { + runApplication(*args) +} diff --git a/src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml b/src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000..1fcf7233d0 --- /dev/null +++ b/src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml @@ -0,0 +1,4 @@ +spring.application.name: websocket +server.port: 25914 + +group: ${spring.cloud.consul.discovery.instance-id} diff --git a/src/backend/websocket/build.gradle.kts b/src/backend/websocket/build.gradle.kts new file mode 100644 index 0000000000..aa1c8e01b8 --- /dev/null +++ b/src/backend/websocket/build.gradle.kts @@ -0,0 +1,30 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED " AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ diff --git a/src/gateway/auth.conf b/src/gateway/auth.conf index ff05036afc..7e66552fe0 100644 --- a/src/gateway/auth.conf +++ b/src/gateway/auth.conf @@ -5,3 +5,9 @@ internal; content_by_lua_file 'conf/lua/auth/auth_web.lua'; } + + # websocket验证身份 + location = /auth/websocket { + internal; + content_by_lua_file 'conf/lua/auth/auth_websocket.lua'; + } \ No newline at end of file diff --git a/src/gateway/lua/auth/auth_web.lua b/src/gateway/lua/auth/auth_web.lua index 3471d42bea..661ba3bc18 100644 --- a/src/gateway/lua/auth/auth_web.lua +++ b/src/gateway/lua/auth/auth_web.lua @@ -52,6 +52,9 @@ elseif config.auth_mode == "ticket" then local bk_ticket = cookieUtil:get_cookie("bk_ticket") if bk_ticket == nil then bk_ticket = ngx.var.http_x_devops_bk_ticket + if bk_ticket == nil then + bk_ticket = urlUtil:parseUrl(ngx.var.request_uri)["x-devops-bk-ticket"] + end if bk_ticket == nil then ngx.exit(401) return @@ -63,6 +66,9 @@ elseif config.auth_mode == "odc" then local bk_token = cookieUtil:get_cookie("bk_token") if bk_token == nil then bk_token = ngx.var.http_x_devops_bk_token + if bk_token == nil then + bk_token = urlUtil:parseUrl(ngx.var.request_uri)["x-devops-bk-token"] + end if bk_token == nil then ngx.exit(401) return diff --git a/src/gateway/lua/auth/auth_websocket.lua b/src/gateway/lua/auth/auth_websocket.lua new file mode 100644 index 0000000000..39a6e32ad8 --- /dev/null +++ b/src/gateway/lua/auth/auth_websocket.lua @@ -0,0 +1,55 @@ +--[[ +Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + +Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + +BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + +A copy of the MIT License is included in this file. + + +Terms of the MIT License: +--------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] + +--- 获取Url请求参数中bk_token 和 bk_ticket + +local token, username + +local bk_ticket = urlUtil:parseUrl(ngx.var.request_uri)["x-devops-bk-ticket"] +local bk_token = urlUtil:parseUrl(ngx.var.request_uri)["x-devops-bk-token"] +local platform_token = ngx.var.http_authorization + +if platform_token ~= nil and string.find(string.lower(platform_token), "^platform") then + ngx.header["x-bkrepo-authorization"] = platform_token + ngx.header["x-bkrepo-uid"] = ngx.var.http_x_bkrepo_uid + ngx.exit(200) + return +end + +if bk_ticket == nil and bk_token == nil then + ngx.exit(401) + return +end + +if bk_ticket ~= nil then + username = oauthUtil:verify_ticket(bk_ticket, "ticket") + token = bk_ticket +end + +if bk_token ~= nil then + username = oauthUtil:verify_tai_token(bk_token) + token = bk_token +end + +--- 设置用户信息 +ngx.header["x-bkrepo-authorization"] = config.bkrepo.authorization +ngx.header["x-bkrepo-uid"] = username +ngx.header["x-bkrepo-bk-token"] = token +ngx.header["x-bkrepo-access-token"] = token +ngx.exit(200) diff --git a/src/gateway/lua/router_srv.lua b/src/gateway/lua/router_srv.lua index d27d6f3446..7eb361df0e 100644 --- a/src/gateway/lua/router_srv.lua +++ b/src/gateway/lua/router_srv.lua @@ -20,7 +20,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI -- 访问限制微服务 -- local allow_services = { "auth", "repository", "generic", "docker", "oci", "maven", "job", "helm", "pypi", "opdata", "rpm", "s3", "git", "npm", "fs-server", "analyst", - "replication", "git", "nuget", "composer", "media", "ddc", "conan", "job-schedule" } + "replication", "git", "nuget", "composer", "media", "ddc", "conan", "job-schedule", "websocket" } local service_name = ngx.var.service if not arrayUtil:isInArray(service_name, allow_services) then diff --git a/src/gateway/vhosts/bkrepo.websocket.conf b/src/gateway/vhosts/bkrepo.websocket.conf new file mode 100644 index 0000000000..c9afe23b3f --- /dev/null +++ b/src/gateway/vhosts/bkrepo.websocket.conf @@ -0,0 +1,47 @@ +location ~ (/web|)/websocket/(ws/user/.*|ws/desktop/.*) { + header_filter_by_lua_file 'conf/lua/cors_filter.lua'; + auth_request /auth/websocket; + # 设置auth的变量 + auth_request_set $uid $sent_http_x_bkrepo_uid; + auth_request_set $accessToken $sent_http_x_bkrepo_access_token; + auth_request_set $bk_token $sent_http_x_bkrepo_bk_token; + auth_request_set $authorization $sent_http_x_bkrepo_authorization; + + set $service "websocket"; + set $path $2; + set $target ''; + + access_by_lua_file 'conf/lua/router_srv.lua'; + proxy_set_header X-BKREPO-UID $uid; + proxy_set_header X-DEVOPS-BK-TOKEN $bk_token; + proxy_set_header X-DEVOPS-BK-TICKET $bk_token; + proxy_set_header X-DEVOPS-ACCESS-TOKEN $accessToken; + proxy_set_header authorization $authorization; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + + proxy_http_version 1.1; + proxy_pass http://$target/$path?$args; +} + +location ~ /websocket/(ws/app.*) { + set $service "websocket"; + set $path $1; + set $target ''; + + access_by_lua_file 'conf/lua/router_srv.lua'; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header Upgrade "websocket"; + proxy_set_header Connection "Upgrade"; + proxy_http_version 1.1; + proxy_pass http://$target/$path?$args; +} diff --git a/support-files/templates/gateway#vhosts#bkrepo.server.conf b/support-files/templates/gateway#vhosts#bkrepo.server.conf index e7d1278bc4..d0c1864a47 100644 --- a/support-files/templates/gateway#vhosts#bkrepo.server.conf +++ b/support-files/templates/gateway#vhosts#bkrepo.server.conf @@ -41,6 +41,9 @@ server { # web接口网关路径 include vhosts/bkrepo.web.conf; + # websocket网关路径 + include vhosts/bkrepo.websocket.conf; + # 后台的网关路径 include vhosts/bkrepo.backend.conf; }