Skip to content

Commit fc06129

Browse files
authored
Merge pull request #127 from Schlaumeier5/91-session-validation
SessionManager improvements
2 parents 9ddd7ec + 788b00f commit fc06129

File tree

2 files changed

+60
-13
lines changed

2 files changed

+60
-13
lines changed

src/main/java/de/igslandstuhl/database/server/webserver/SessionManager.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ public class SessionManager {
1414
* A map to store session IDs and their associated usernames.
1515
* This is a simple in-memory session store.
1616
*/
17-
private Map<Session, String> sessionUsers = new HashMap<>();
18-
private Map<Session, Instant> lastActivity = new HashMap<>();
19-
private Map<Session, Integer> requestCount = new HashMap<>();
17+
private SessionStorage<String> sessionUsers = new SessionStorage<>();
18+
private SessionStorage<Instant> lastActivity = new SessionStorage<>();
19+
private SessionStorage<Integer> requestCount = new SessionStorage<>();
2020

2121
/**
2222
* After this duration, sessions expire (are removed from the session store). It is measured in seconds.
@@ -65,18 +65,28 @@ private void cleanSecondsJob() {
6565
}
6666

6767
public boolean validateSession(HttpRequest request) {
68-
Session session = getSession(request);
69-
lastActivity.put(session, Instant.now());
68+
lastActivity.set(request, Instant.now());
7069

71-
Integer requests = requestCount.get(session);
70+
Integer requests = requestCount.get(request);
7271
int count = requests == null ? 0 : requests;
7372
count++;
74-
requestCount.put(session, count);
73+
requestCount.set(request, count);
7574
if (count > maxRequests && !getSessionUser(request).isAdmin()) {
7675
System.out.println("Ratelimit!");
7776
return false;
7877
}
7978

79+
String userAgent = request.getUserAgent();
80+
if (!getSession(request).getUserAgent().equals(userAgent)) {
81+
System.err.println("SEVERE WARNING: POTENTIAL ATTACK: faked session id (device changed), for user " + getSessionUser(request));
82+
return false;
83+
}
84+
String ip = request.getIP();
85+
if (!getSession(request).getIpAddress().equals(ip)) {
86+
System.err.println("SEVERE WARNING: POTENTIAL ATTACK: faked session id (ip address changed) for user " + getSessionUser(request));
87+
return false;
88+
}
89+
8090
return true;
8191
}
8292

@@ -120,12 +130,9 @@ public User getSessionUser(HttpRequest request) {
120130
*/
121131
public void addSessionUser(Session session, String username) {
122132
// Remove all previous sessions for this user (see #51)
123-
if (sessionUsers.values().contains(username)) {
124-
sessionUsers.keySet().stream()
125-
.filter((k) -> sessionUsers.get(k).equals(username))
126-
.toList() // Convert to list to prevent ConcurrentModificationException
127-
.forEach((k) -> sessionUsers.remove(k));
133+
if (sessionUsers.contains(username)) {
134+
sessionUsers.remove(username);
128135
}
129-
sessionUsers.put(session, username);
136+
sessionUsers.set(session, username);
130137
}
131138
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package de.igslandstuhl.database.server.webserver;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import de.igslandstuhl.database.server.Server;
7+
import de.igslandstuhl.database.server.webserver.requests.HttpRequest;
8+
9+
public class SessionStorage<T> {
10+
private final Map<Session, T> intern = new HashMap<>();
11+
12+
public T get(Session session) {
13+
return intern.get(session);
14+
}
15+
public T get(HttpRequest request) {
16+
return intern.get(Server.getInstance().getWebServer().getSessionManager().getSession(request));
17+
}
18+
public void set(Session session, T object) {
19+
intern.put(session, object);
20+
}
21+
public void set(HttpRequest request, T object) {
22+
intern.put(Server.getInstance().getWebServer().getSessionManager().getSession(request), object);
23+
}
24+
public void remove(Session session) {
25+
intern.remove(session);
26+
}
27+
public void remove(Session session, T value) {
28+
intern.remove(session,value);
29+
}
30+
public void remove(T value) {
31+
intern.keySet().stream().filter((key) -> intern.get(key) == value)
32+
.toList().forEach((k) -> remove(k));
33+
}
34+
public boolean contains(T value) {
35+
return intern.values().contains(value);
36+
}
37+
public void clear() {
38+
intern.clear();
39+
}
40+
}

0 commit comments

Comments
 (0)