diff --git a/pom.xml b/pom.xml index b091ba6..741bb24 100644 --- a/pom.xml +++ b/pom.xml @@ -42,14 +42,6 @@ io.quarkus quarkus-config-yaml - - io.quarkus - quarkus-smallrye-graphql - - - io.quarkus - quarkus-reactive-routes - io.quarkus quarkus-arc diff --git a/src/main/java/dev/struchkov/example/CustomConfigurator.java b/src/main/java/dev/struchkov/example/CustomConfigurator.java new file mode 100644 index 0000000..c32cb80 --- /dev/null +++ b/src/main/java/dev/struchkov/example/CustomConfigurator.java @@ -0,0 +1,36 @@ +package dev.struchkov.example; + +import jakarta.websocket.HandshakeResponse; +import jakarta.websocket.server.HandshakeRequest; +import jakarta.websocket.server.ServerEndpointConfig; + +import java.util.List; +import java.util.Map; + +public class CustomConfigurator extends ServerEndpointConfig.Configurator { + + @Override + public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) { + final Map> headers = request.getHeaders(); + final List cookies = headers.get("cookie"); + + String sessionId = parseCookies(cookies); // ваша реализация парсинга кук + config.getUserProperties().put("sessionId", sessionId); + } + + public String parseCookies(List cookies) { + if (cookies != null) { + for (String cookie : cookies) { + String[] singleCookie = cookie.split(";"); + for (String part : singleCookie) { + part = part.trim(); + if (part.startsWith("sessionId")) { + return part.substring("sessionId".length() + 1).trim(); + } + } + } + } + return null; + } + +} diff --git a/src/main/java/dev/struchkov/example/GreetingConfig.java b/src/main/java/dev/struchkov/example/GreetingConfig.java deleted file mode 100644 index b67c55a..0000000 --- a/src/main/java/dev/struchkov/example/GreetingConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package dev.struchkov.example; - -import io.smallrye.config.ConfigMapping; -import io.smallrye.config.WithName; - -@ConfigMapping(prefix = "greeting") -public interface GreetingConfig { - - @WithName("message") - String message(); - -} \ No newline at end of file diff --git a/src/main/java/dev/struchkov/example/HelloGraphQLResource.java b/src/main/java/dev/struchkov/example/HelloGraphQLResource.java deleted file mode 100644 index 618e496..0000000 --- a/src/main/java/dev/struchkov/example/HelloGraphQLResource.java +++ /dev/null @@ -1,17 +0,0 @@ -package dev.struchkov.example; - -import org.eclipse.microprofile.graphql.DefaultValue; -import org.eclipse.microprofile.graphql.Description; -import org.eclipse.microprofile.graphql.GraphQLApi; -import org.eclipse.microprofile.graphql.Query; - -@GraphQLApi -public class HelloGraphQLResource { - - @Query - @Description("Say hello") - public String sayHello(@DefaultValue("World") String name) { - return "Hello " + name; - } - -} \ No newline at end of file diff --git a/src/main/java/dev/struchkov/example/StartWebSocket.java b/src/main/java/dev/struchkov/example/WebSocket.java similarity index 59% rename from src/main/java/dev/struchkov/example/StartWebSocket.java rename to src/main/java/dev/struchkov/example/WebSocket.java index 7c2234c..57623e0 100644 --- a/src/main/java/dev/struchkov/example/StartWebSocket.java +++ b/src/main/java/dev/struchkov/example/WebSocket.java @@ -1,5 +1,10 @@ package dev.struchkov.example; +import dev.struchkov.example.converter.ChatMessageDecoder; +import dev.struchkov.example.converter.ChatMessageEncoder; +import dev.struchkov.example.domain.ChatInputMessage; +import dev.struchkov.example.domain.ChatOutputMessage; +import io.vertx.ext.web.handler.HttpException; import jakarta.enterprise.context.ApplicationScoped; import jakarta.websocket.OnClose; import jakarta.websocket.OnError; @@ -21,31 +26,55 @@ import java.util.concurrent.ConcurrentHashMap; @ServerEndpoint( value = "/chat/{chatId}", decoders = ChatMessageDecoder.class, - encoders = ChatMessageEncoder.class + encoders = ChatMessageEncoder.class, + configurator = CustomConfigurator.class ) @RequiredArgsConstructor -public class StartWebSocket { +public class WebSocket { - public static final ThreadLocal CURRENT_USER = new ThreadLocal<>(); private final Map> sessions = new ConcurrentHashMap<>(); @OnOpen public void onOpen(Session session, @PathParam("chatId") String chatId) { System.out.println("onOpen> " + chatId); + final String authCookieValue = (String) session.getUserProperties().get("sessionId"); + final UUID authUserId = getAuthUser(authCookieValue); + session.getUserProperties().put("userId", authUserId); sessions.computeIfAbsent(chatId, key -> new ArrayList<>()).add(session); } + private UUID getAuthUser(String authCookieValue) { + // your auth logic here + if (authCookieValue == null) throw new HttpException(401, "Не передан параметр авторизации."); + if (authCookieValue.equals("user1")) return UUID.fromString("09e429de-a302-40b6-9d10-6b113ab9e89d"); + if (authCookieValue.equals("user2")) return UUID.fromString("f84dbae1-f9a9-4c37-8922-4eb207103676"); + throw new HttpException(403, "Пользователь не авторизован."); + } + + @OnError + public void onError(Session session, @PathParam("chatId") String chatId, Throwable throwable) { + if (throwable instanceof HttpException httpException) { + final int statusCode = httpException.getStatusCode(); + if (statusCode == 401) { + session.getAsyncRemote().sendText("Вы не авторизованы."); + closeSession(session, chatId); + return; + } + if (statusCode == 403) { + session.getAsyncRemote().sendText("Доступ запрещен."); + closeSession(session, chatId); + return; + } + } + System.out.println("onError> " + chatId + ": " + throwable); + } + @OnClose public void onClose(Session session, @PathParam("chatId") String chatId) { System.out.println("onClose> " + chatId); closeSession(session, chatId); } - @OnError - public void onError(Session session, @PathParam("chatId") String chatId, Throwable throwable) { - System.out.println("onError> " + chatId + ": " + throwable); - } - @OnMessage public void onMessage(Session session, @PathParam("chatId") String chatId, ChatInputMessage message) { System.out.println("onMessage> " + chatId + ": " + message); @@ -58,10 +87,9 @@ public class StartWebSocket { if (session.getId().equals(chatSession.getId())) { continue; } - final UUID fromUserId = CURRENT_USER.get(); + final UUID fromUserId = (UUID) session.getUserProperties().get("userId"); final ChatOutputMessage outputMessage = new ChatOutputMessage(fromUserId, message.getText()); chatSession.getAsyncRemote().sendObject(outputMessage); - CURRENT_USER.remove(); } } diff --git a/src/main/java/dev/struchkov/example/WebsocketAuthFilter.java b/src/main/java/dev/struchkov/example/WebsocketAuthFilter.java deleted file mode 100644 index 97c03be..0000000 --- a/src/main/java/dev/struchkov/example/WebsocketAuthFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -package dev.struchkov.example; - -import io.quarkus.vertx.web.RouteFilter; -import io.vertx.core.http.Cookie; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.ext.web.RoutingContext; -import io.vertx.ext.web.handler.HttpException; -import lombok.RequiredArgsConstructor; - -import java.util.UUID; - -@RequiredArgsConstructor -public class WebsocketAuthFilter { - - @RouteFilter(100) - void authFilter(RoutingContext rc) { - final HttpServerRequest currentRequest = rc.request(); - - if (isWebsocketRequest(currentRequest)) { - final Cookie authCookie = currentRequest.getCookie("sessionId"); - if (authCookie == null) { - throw new HttpException(401, "Не передан параметр авторизации."); - } - - final String authValue = authCookie.getValue(); - if (!authLogic(authValue)) { - throw new HttpException(403, "Пользователь не авторизован."); - } - } - - rc.next(); - } - - private static boolean isWebsocketRequest(HttpServerRequest currentRequest) { - return currentRequest.headers().contains("Upgrade") - && "websocket".equals(currentRequest.getHeader("Upgrade")); - } - - private boolean authLogic(String sessionId) { - // your auth logic here - if (sessionId.equals("user1")) { - StartWebSocket.CURRENT_USER.set(UUID.fromString("09e429de-a302-40b6-9d10-6b113ab9e89d")); - return true; - } else if (sessionId.equals("user2")) { - StartWebSocket.CURRENT_USER.set(UUID.fromString("f84dbae1-f9a9-4c37-8922-4eb207103676")); - return true; - } else { - return false; - } - } - -} diff --git a/src/main/java/dev/struchkov/example/ChatMessageDecoder.java b/src/main/java/dev/struchkov/example/converter/ChatMessageDecoder.java similarity index 91% rename from src/main/java/dev/struchkov/example/ChatMessageDecoder.java rename to src/main/java/dev/struchkov/example/converter/ChatMessageDecoder.java index 7c6ab67..0c668cd 100644 --- a/src/main/java/dev/struchkov/example/ChatMessageDecoder.java +++ b/src/main/java/dev/struchkov/example/converter/ChatMessageDecoder.java @@ -1,9 +1,10 @@ -package dev.struchkov.example; +package dev.struchkov.example.converter; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import dev.struchkov.example.domain.ChatInputMessage; import jakarta.websocket.DecodeException; import jakarta.websocket.Decoder; import lombok.SneakyThrows; diff --git a/src/main/java/dev/struchkov/example/ChatMessageEncoder.java b/src/main/java/dev/struchkov/example/converter/ChatMessageEncoder.java similarity index 83% rename from src/main/java/dev/struchkov/example/ChatMessageEncoder.java rename to src/main/java/dev/struchkov/example/converter/ChatMessageEncoder.java index 2798f58..244c1cd 100644 --- a/src/main/java/dev/struchkov/example/ChatMessageEncoder.java +++ b/src/main/java/dev/struchkov/example/converter/ChatMessageEncoder.java @@ -1,6 +1,7 @@ -package dev.struchkov.example; +package dev.struchkov.example.converter; import com.fasterxml.jackson.databind.ObjectMapper; +import dev.struchkov.example.domain.ChatOutputMessage; import jakarta.websocket.EncodeException; import jakarta.websocket.Encoder; import lombok.SneakyThrows; diff --git a/src/main/java/dev/struchkov/example/ChatInputMessage.java b/src/main/java/dev/struchkov/example/domain/ChatInputMessage.java similarity index 80% rename from src/main/java/dev/struchkov/example/ChatInputMessage.java rename to src/main/java/dev/struchkov/example/domain/ChatInputMessage.java index 1ebbe10..b5145c0 100644 --- a/src/main/java/dev/struchkov/example/ChatInputMessage.java +++ b/src/main/java/dev/struchkov/example/domain/ChatInputMessage.java @@ -1,4 +1,4 @@ -package dev.struchkov.example; +package dev.struchkov.example.domain; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/dev/struchkov/example/ChatOutputMessage.java b/src/main/java/dev/struchkov/example/domain/ChatOutputMessage.java similarity index 87% rename from src/main/java/dev/struchkov/example/ChatOutputMessage.java rename to src/main/java/dev/struchkov/example/domain/ChatOutputMessage.java index 0c3867c..e5fdad8 100644 --- a/src/main/java/dev/struchkov/example/ChatOutputMessage.java +++ b/src/main/java/dev/struchkov/example/domain/ChatOutputMessage.java @@ -1,4 +1,4 @@ -package dev.struchkov.example; +package dev.struchkov.example.domain; import lombok.AllArgsConstructor; import lombok.Getter;