рефакторинг
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -42,14 +42,6 @@
|
|||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-config-yaml</artifactId>
|
<artifactId>quarkus-config-yaml</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.quarkus</groupId>
|
|
||||||
<artifactId>quarkus-smallrye-graphql</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.quarkus</groupId>
|
|
||||||
<artifactId>quarkus-reactive-routes</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-arc</artifactId>
|
<artifactId>quarkus-arc</artifactId>
|
||||||
|
|||||||
36
src/main/java/dev/struchkov/example/CustomConfigurator.java
Normal file
36
src/main/java/dev/struchkov/example/CustomConfigurator.java
Normal file
@@ -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<String, List<String>> headers = request.getHeaders();
|
||||||
|
final List<String> cookies = headers.get("cookie");
|
||||||
|
|
||||||
|
String sessionId = parseCookies(cookies); // ваша реализация парсинга кук
|
||||||
|
config.getUserProperties().put("sessionId", sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String parseCookies(List<String> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
package dev.struchkov.example;
|
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.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.websocket.OnClose;
|
import jakarta.websocket.OnClose;
|
||||||
import jakarta.websocket.OnError;
|
import jakarta.websocket.OnError;
|
||||||
@@ -21,31 +26,55 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
@ServerEndpoint(
|
@ServerEndpoint(
|
||||||
value = "/chat/{chatId}",
|
value = "/chat/{chatId}",
|
||||||
decoders = ChatMessageDecoder.class,
|
decoders = ChatMessageDecoder.class,
|
||||||
encoders = ChatMessageEncoder.class
|
encoders = ChatMessageEncoder.class,
|
||||||
|
configurator = CustomConfigurator.class
|
||||||
)
|
)
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class StartWebSocket {
|
public class WebSocket {
|
||||||
|
|
||||||
public static final ThreadLocal<UUID> CURRENT_USER = new ThreadLocal<>();
|
|
||||||
private final Map<String, List<Session>> sessions = new ConcurrentHashMap<>();
|
private final Map<String, List<Session>> sessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@OnOpen
|
@OnOpen
|
||||||
public void onOpen(Session session, @PathParam("chatId") String chatId) {
|
public void onOpen(Session session, @PathParam("chatId") String chatId) {
|
||||||
System.out.println("onOpen> " + 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);
|
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
|
@OnClose
|
||||||
public void onClose(Session session, @PathParam("chatId") String chatId) {
|
public void onClose(Session session, @PathParam("chatId") String chatId) {
|
||||||
System.out.println("onClose> " + chatId);
|
System.out.println("onClose> " + chatId);
|
||||||
closeSession(session, chatId);
|
closeSession(session, chatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnError
|
|
||||||
public void onError(Session session, @PathParam("chatId") String chatId, Throwable throwable) {
|
|
||||||
System.out.println("onError> " + chatId + ": " + throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnMessage
|
@OnMessage
|
||||||
public void onMessage(Session session, @PathParam("chatId") String chatId, ChatInputMessage message) {
|
public void onMessage(Session session, @PathParam("chatId") String chatId, ChatInputMessage message) {
|
||||||
System.out.println("onMessage> " + chatId + ": " + message);
|
System.out.println("onMessage> " + chatId + ": " + message);
|
||||||
@@ -58,10 +87,9 @@ public class StartWebSocket {
|
|||||||
if (session.getId().equals(chatSession.getId())) {
|
if (session.getId().equals(chatSession.getId())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final UUID fromUserId = CURRENT_USER.get();
|
final UUID fromUserId = (UUID) session.getUserProperties().get("userId");
|
||||||
final ChatOutputMessage outputMessage = new ChatOutputMessage(fromUserId, message.getText());
|
final ChatOutputMessage outputMessage = new ChatOutputMessage(fromUserId, message.getText());
|
||||||
chatSession.getAsyncRemote().sendObject(outputMessage);
|
chatSession.getAsyncRemote().sendObject(outputMessage);
|
||||||
CURRENT_USER.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
package dev.struchkov.example;
|
package dev.struchkov.example.converter;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import dev.struchkov.example.domain.ChatInputMessage;
|
||||||
import jakarta.websocket.DecodeException;
|
import jakarta.websocket.DecodeException;
|
||||||
import jakarta.websocket.Decoder;
|
import jakarta.websocket.Decoder;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.struchkov.example;
|
package dev.struchkov.example.converter;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import dev.struchkov.example.domain.ChatOutputMessage;
|
||||||
import jakarta.websocket.EncodeException;
|
import jakarta.websocket.EncodeException;
|
||||||
import jakarta.websocket.Encoder;
|
import jakarta.websocket.Encoder;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.struchkov.example;
|
package dev.struchkov.example.domain;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.struchkov.example;
|
package dev.struchkov.example.domain;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
Reference in New Issue
Block a user