Commit c97cb881c00baeddbe0267aebbfd6d5cd59b88fd

Authored by Thomas Ziemer
1 parent 0065756c

feature: REST-Login vor WebSocket-Erstellung in der HTML-Seite

src/main/java/net/ziemers/swxercise/lg/model/user/User.java
... ... @@ -46,6 +46,11 @@ public class User extends BaseEntity {
46 46 this.lastname = lastname;
47 47 }
48 48  
  49 + @Transient
  50 + public String getFullName() {
  51 + return String.format("%s %s", getFirstname(), getLastname());
  52 + }
  53 +
49 54 @OneToOne(cascade = {CascadeType.ALL})
50 55 public Profile getProfile() {
51 56 return profile;
... ...
src/main/java/net/ziemers/swxercise/lg/user/service/SessionContext.java
1 1 package net.ziemers.swxercise.lg.user.service;
2 2  
  3 +import javax.annotation.PreDestroy;
3 4 import javax.enterprise.context.SessionScoped;
4 5  
5 6 import net.ziemers.swxercise.lg.model.user.User;
6 7  
  8 +import java.util.Collections;
  9 +import java.util.HashMap;
  10 +import java.util.Map;
  11 +
7 12 /**
8 13 * Verwaltet den SessionContext des zurzeit angemeldeten Benutzers.
9 14 */
... ... @@ -12,10 +17,17 @@ public class SessionContext implements java.io.Serializable {
12 17  
13 18 private static final long serialVersionUID = 8624253586553865146L;
14 19  
  20 + private static Map<String, SessionContext> sessions = Collections.synchronizedMap(new HashMap<>());
  21 +
15 22 private User user = null;
16 23  
17 24 private String sessionId = "";
18 25  
  26 + @PreDestroy
  27 + private void deinit() {
  28 + sessions.remove(getSessionId());
  29 + }
  30 +
19 31 public User getUser() {
20 32 return user;
21 33 }
... ... @@ -24,29 +36,52 @@ public class SessionContext implements java.io.Serializable {
24 36 this.user = user;
25 37 }
26 38  
27   - public String getSessionId() { return sessionId; }
  39 + private String getSessionId() { return sessionId; }
28 40  
29 41 private void setSessionId(String sessionId) { this.sessionId = sessionId; }
30 42  
31 43 /**
  44 + * Liefert den Session-Kontext zur übergebenen REST-Session-Id.
  45 + *
  46 + * @param restSessionId die REST-Session-Id, deren Session-Kontext ermittelt werden soll
  47 + * @return das {@link SessionContext}-Objekt des Benutzers mit der REST-Session-Id oder <code>null</code>.
  48 + */
  49 + public static SessionContext getInstanceByRestSessionId(final String restSessionId) {
  50 + return sessions.get(restSessionId);
  51 + }
  52 +
  53 + /**
32 54 * Meldet einen Benutzer in diesem Session-Kontext an.
33 55 *
34 56 * @param user das {@link User}-Objekt des Benutzers dieses Session-Kontexts
35 57 * @param sessionId die Session-Id dieser Benutzer-Session
36   - * @return Liefert <code>true</code> zurück, wenn der Benutzer am Session-Kontext angemeldet werden konnte.
  58 + * @return <code>true</code>, wenn der Benutzer erfolgreich am Session-Kontext angemeldet werden konnte.
37 59 */
38 60 public boolean login(final User user, final String sessionId) {
39 61 if (getUser() == null) {
40 62 setUser(user);
41 63 setSessionId(sessionId);
  64 +
  65 + // wir können später von der Session-Id auf den Session-Kontext schließen
  66 + sessions.putIfAbsent(getSessionId(), this);
  67 +
42 68 return true;
43 69 }
44 70 return false;
45 71 }
46 72  
  73 + /**
  74 + * Meldet einen Benutzer von diesem Session-Kontext ab.
  75 + *
  76 + * @return <code>true</code>, wenn die Abmeldung erfolgreich durchgeführt werden konnte.
  77 + */
47 78 public boolean logout() {
48 79 if (getUser() != null) {
49 80 setUser(null);
  81 +
  82 + // ohne authentifizierten Benutzer interessiert uns dieser Session-Kontext nicht mehr
  83 + sessions.remove(getSessionId());
  84 +
50 85 return true;
51 86 }
52 87 return false;
... ...
src/main/java/net/ziemers/swxercise/ui/ws/WebSocketController.java
1 1 package net.ziemers.swxercise.ui.ws;
2 2  
  3 +import net.ziemers.swxercise.lg.model.user.User;
  4 +import net.ziemers.swxercise.lg.user.service.SessionContext;
3 5 import org.slf4j.Logger;
4 6 import org.slf4j.LoggerFactory;
5 7  
... ... @@ -54,6 +56,8 @@ public class WebSocketController {
54 56  
55 57 // wir können später über die gegebene WebSocket-Session die REST-Session-Id dieses WebSockets ermitteln
56 58 peers.putIfAbsent(wsSession, restSessionId);
  59 +
  60 + getUserBySession(wsSession);
57 61 }
58 62  
59 63 /**
... ... @@ -64,11 +68,10 @@ public class WebSocketController {
64 68 */
65 69 @OnMessage
66 70 public void onMessage(WebSocketJson json, Session wsSession) throws IOException, EncodeException {
67   - // die Map liefert uns zur gegebenen WebSocket-Session die REST-Session-Id zurück
68   - String restSessionId = peers.get(wsSession);
  71 + logger.info("WebSocket Message '{}' received by session id #{}", json.getMessage(), wsSession.getId());
  72 +
  73 + getUserBySession(wsSession);
69 74  
70   - logger.info("WebSocket {} Message '{}' received by session id #{}",
71   - restSessionId, json.getMessage(), wsSession.getId());
72 75 try {
73 76 // Wir senden die empfangene Nachricht gleich wieder zurück. Das JSON-Marshalling geschieht automatisch.
74 77 wsSession.getBasicRemote().sendObject(json);
... ... @@ -99,4 +102,20 @@ public class WebSocketController {
99 102 peers.remove(wsSession);
100 103 }
101 104  
  105 + private User getUserBySession(final Session wsSession) {
  106 + // die Map liefert uns zur WebSocket-Session gegebenenfalls die REST-Session-Id zurück;
  107 + // und mit dieser schließen wir auf den authentifizierten REST-Benutzer
  108 + String restSessionId = WebSocketController.peers.get(wsSession);
  109 + SessionContext ctx = SessionContext.getInstanceByRestSessionId(restSessionId);
  110 +
  111 + if (ctx != null) {
  112 + User user = ctx.getUser();
  113 +
  114 + logger.info("Detected WebSocket User '{}'", user.getFullName());
  115 +
  116 + return user;
  117 + }
  118 + return null;
  119 + }
  120 +
102 121 }
... ...
src/main/java/net/ziemers/swxercise/ui/ws/WebSocketJson.java
... ... @@ -23,21 +23,18 @@ public class WebSocketJson {
23 23 public static class MessageEncoder implements Encoder.Text<WebSocketJson> {
24 24  
25 25 @Override
26   - public void init(EndpointConfig config) {
27   - }
  26 + public void init(EndpointConfig config) {}
28 27  
29 28 @Override
30 29 public String encode(WebSocketJson message) throws EncodeException {
31 30 return Json.createObjectBuilder()
32   - .add("username", message.getUsername())
33 31 .add("message", message.getMessage())
34 32 .build()
35 33 .toString();
36 34 }
37 35  
38 36 @Override
39   - public void destroy() {
40   - }
  37 + public void destroy() {}
41 38  
42 39 }
43 40  
... ... @@ -49,8 +46,7 @@ public class WebSocketJson {
49 46 private JsonReaderFactory factory = Json.createReaderFactory(Collections.emptyMap());
50 47  
51 48 @Override
52   - public void init(EndpointConfig config) {
53   - }
  49 + public void init(EndpointConfig config) {}
54 50  
55 51 @Override
56 52 public WebSocketJson decode(String str) throws DecodeException {
... ... @@ -58,7 +54,6 @@ public class WebSocketJson {
58 54 JsonReader reader = factory.createReader(new StringReader(str));
59 55 JsonObject json = reader.readObject();
60 56  
61   - message.setUsername(json.getString("username"));
62 57 message.setMessage(json.getString("message"));
63 58  
64 59 return message;
... ... @@ -70,28 +65,17 @@ public class WebSocketJson {
70 65 }
71 66  
72 67 @Override
73   - public void destroy() {
74   - }
  68 + public void destroy() {}
75 69  
76 70 }
77 71  
78 72 /*
79 73 * Payload der JSON-Nachricht
80 74 */
81   - private String username;
82   -
83 75 private String message;
84 76  
85 77 private WebSocketJson() {}
86 78  
87   - public String getUsername() {
88   - return username;
89   - }
90   -
91   - private void setUsername(String username) {
92   - this.username = username;
93   - }
94   -
95 79 public String getMessage() {
96 80 return message;
97 81 }
... ...
src/main/webapp/websockets.html
... ... @@ -7,45 +7,64 @@
7 7  
8 8 <body>
9 9 <script>
10   - // sei "4711" die in einer vorangegangenen REST-Authentifizierung ermittelte "restSessionId"
11   - var restSessionId = 4711;
  10 + // Anmelden und REST-Session-Id erhalten
  11 + var restUrl = "http://localhost:8080/swxercise/rest/v1/user/login";
  12 + var method = "POST";
  13 + var jsObject = { "username": "admin", "password": "admin" };
  14 + var xmlHttpRequest = new XMLHttpRequest();
12 15  
13   - var url = "ws://localhost:8080/swxercise/ws/api/v1/anEndpoint/" + restSessionId;
14   - var webSocket = new WebSocket(url);
  16 + xmlHttpRequest.open(method, restUrl);
  17 + xmlHttpRequest.setRequestHeader("Content-type", "application/json");
  18 + xmlHttpRequest.onreadystatechange = function() {
  19 + if (this.readyState === 4 && this.status === 200) {
  20 + var jsResponse = JSON.parse(this.responseText);
15 21  
16   - // Callback-Methoden für die WebSocket-Kommunikation
17   - webSocket.onopen = function(e) { onWebSocketOpen(e) };
18   - webSocket.onclose = function(e) { onWebSocketClose(e) };
19   - webSocket.onmessage = function(e) { onWebSocketMessage(e) };
20   - webSocket.onerror = function(e) { onWebSocketError(e) };
  22 + establishWebSocket(jsResponse.message);
21 23  
22   - function onWebSocketOpen(e) {
23   - console.log("WebSocket has been opened.");
24   - }
  24 + console.log("REST-Session-Id is '" + jsResponse.message + "'.");
  25 + }
  26 + };
  27 + xmlHttpRequest.send(JSON.stringify(jsObject));
25 28  
26   - function onWebSocketClose(e) {
27   - console.log("WebSocket has been closed.");
28   - }
  29 + // WebSocket-Verbindung etablieren
  30 + var webSocket;
29 31  
30   - function onWebSocketMessage(e) {
31   - // JSON-String in ein JavaScript-Objekt konvertieren
32   - var json = JSON.parse(e.data);
  32 + function establishWebSocket(restSessionId) {
  33 + var wsUrl = "ws://localhost:8080/swxercise/ws/api/v1/anEndpoint/" + restSessionId;
33 34  
34   - console.log("WebSocket Message '" + json.message + "' has been received.");
35   - }
  35 + webSocket = new WebSocket(wsUrl);
  36 +
  37 + // Callback-Methoden für die WebSocket-Kommunikation
  38 + webSocket.onopen = function(e) { onWebSocketOpen(e) };
  39 + webSocket.onclose = function(e) { onWebSocketClose(e) };
  40 + webSocket.onmessage = function(e) { onWebSocketMessage(e) };
  41 + webSocket.onerror = function(e) { onWebSocketError(e) };
  42 +
  43 + function onWebSocketOpen(e) {
  44 + console.log("WebSocket has been opened.");
  45 + }
36 46  
37   - function onWebSocketError(e) {
38   - alert("WebSocket Error " + e + " has been thrown!");
  47 + function onWebSocketClose(e) {
  48 + console.log("WebSocket has been closed.");
  49 + }
  50 +
  51 + function onWebSocketMessage(e) {
  52 + // JSON-String in ein JavaScript-Objekt konvertieren
  53 + var json = JSON.parse(e.data);
  54 +
  55 + console.log("WebSocket Message '" + json.message + "' has been received.");
  56 + }
  57 +
  58 + function onWebSocketError(e) {
  59 + alert("WebSocket Error " + e + " has been thrown!");
  60 + }
39 61 }
40 62  
41 63 function sendWebSocketMessage() {
42   - var json = {
43   - "username": "admin",
44   - "message": "Hello World!"
45   - }
  64 + var jsonPayload = { "message": "Hello World!" };
46 65  
47 66 // JavaScript-Objekt in einen JSON-String konvertieren
48   - webSocket.send(JSON.stringify(json));
  67 + webSocket.send(JSON.stringify(jsonPayload));
49 68  
50 69 console.log("Tried to send WebSocket Message.");
51 70 }
... ...