disable fingerpritning

This commit is contained in:
Anthony Stirling 2024-10-05 09:15:43 +01:00
parent c59d3ff3e0
commit 3b5b7772a9
3 changed files with 279 additions and 279 deletions

View File

@ -1,68 +1,68 @@
package stirling.software.SPDF.config.fingerprint;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.utils.RequestUriUtils;
@Component
@Slf4j
public class FingerprintBasedSessionFilter extends OncePerRequestFilter {
private final FingerprintGenerator fingerprintGenerator;
private final FingerprintBasedSessionManager sessionManager;
@Autowired
public FingerprintBasedSessionFilter(
FingerprintGenerator fingerprintGenerator,
FingerprintBasedSessionManager sessionManager) {
this.fingerprintGenerator = fingerprintGenerator;
this.sessionManager = sessionManager;
}
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (RequestUriUtils.isStaticResource(request.getContextPath(), request.getRequestURI())) {
filterChain.doFilter(request, response);
return;
}
String fingerprint = fingerprintGenerator.generateFingerprint(request);
log.debug("Generated fingerprint for request: {}", fingerprint);
HttpSession session = request.getSession();
boolean isNewSession = session.isNew();
String sessionId = session.getId();
if (isNewSession) {
log.info("New session created: {}", sessionId);
}
if (!sessionManager.isFingerPrintAllowed(fingerprint)) {
log.info("Blocked fingerprint detected, redirecting: {}", fingerprint);
response.sendRedirect(request.getContextPath() + "/too-many-requests");
return;
}
session.setAttribute("userFingerprint", fingerprint);
session.setAttribute(
FingerprintBasedSessionManager.STARTUP_TIMESTAMP,
FingerprintBasedSessionManager.APP_STARTUP_TIME);
sessionManager.registerFingerprint(fingerprint, sessionId);
log.debug("Proceeding with request: {}", request.getRequestURI());
filterChain.doFilter(request, response);
}
}
//package stirling.software.SPDF.config.fingerprint;
//
//import java.io.IOException;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//import org.springframework.web.filter.OncePerRequestFilter;
//
//import jakarta.servlet.FilterChain;
//import jakarta.servlet.ServletException;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import jakarta.servlet.http.HttpSession;
//import lombok.extern.slf4j.Slf4j;
//import stirling.software.SPDF.utils.RequestUriUtils;
//
////@Component
//@Slf4j
//public class FingerprintBasedSessionFilter extends OncePerRequestFilter {
// private final FingerprintGenerator fingerprintGenerator;
// private final FingerprintBasedSessionManager sessionManager;
//
// @Autowired
// public FingerprintBasedSessionFilter(
// FingerprintGenerator fingerprintGenerator,
// FingerprintBasedSessionManager sessionManager) {
// this.fingerprintGenerator = fingerprintGenerator;
// this.sessionManager = sessionManager;
// }
//
// @Override
// protected void doFilterInternal(
// HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
// throws ServletException, IOException {
//
// if (RequestUriUtils.isStaticResource(request.getContextPath(), request.getRequestURI())) {
// filterChain.doFilter(request, response);
// return;
// }
//
// String fingerprint = fingerprintGenerator.generateFingerprint(request);
// log.debug("Generated fingerprint for request: {}", fingerprint);
//
// HttpSession session = request.getSession();
// boolean isNewSession = session.isNew();
// String sessionId = session.getId();
//
// if (isNewSession) {
// log.info("New session created: {}", sessionId);
// }
//
// if (!sessionManager.isFingerPrintAllowed(fingerprint)) {
// log.info("Blocked fingerprint detected, redirecting: {}", fingerprint);
// response.sendRedirect(request.getContextPath() + "/too-many-requests");
// return;
// }
//
// session.setAttribute("userFingerprint", fingerprint);
// session.setAttribute(
// FingerprintBasedSessionManager.STARTUP_TIMESTAMP,
// FingerprintBasedSessionManager.APP_STARTUP_TIME);
//
// sessionManager.registerFingerprint(fingerprint, sessionId);
//
// log.debug("Proceeding with request: {}", request.getRequestURI());
// filterChain.doFilter(request, response);
// }
//}

View File

@ -1,134 +1,134 @@
package stirling.software.SPDF.config.fingerprint;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class FingerprintBasedSessionManager
implements HttpSessionListener, HttpSessionAttributeListener {
private static final ConcurrentHashMap<String, FingerprintInfo> activeFingerprints =
new ConcurrentHashMap<>();
// To be reduced in later version to 8~
private static final int MAX_ACTIVE_FINGERPRINTS = 30;
static final String STARTUP_TIMESTAMP = "appStartupTimestamp";
static final long APP_STARTUP_TIME = System.currentTimeMillis();
private static final long FINGERPRINT_EXPIRATION = TimeUnit.MINUTES.toMillis(30);
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
String sessionId = session.getId();
String fingerprint = (String) session.getAttribute("userFingerprint");
if (fingerprint == null) {
log.warn("Session created without fingerprint: {}", sessionId);
return;
}
synchronized (activeFingerprints) {
if (activeFingerprints.size() >= MAX_ACTIVE_FINGERPRINTS
&& !activeFingerprints.containsKey(fingerprint)) {
log.info("Max fingerprints reached. Marking session as blocked: {}", sessionId);
session.setAttribute("blocked", true);
} else {
activeFingerprints.put(
fingerprint, new FingerprintInfo(sessionId, System.currentTimeMillis()));
log.info(
"New fingerprint registered: {}. Total active fingerprints: {}",
fingerprint,
activeFingerprints.size());
}
session.setAttribute(STARTUP_TIMESTAMP, APP_STARTUP_TIME);
}
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
String fingerprint = (String) session.getAttribute("userFingerprint");
if (fingerprint != null) {
synchronized (activeFingerprints) {
activeFingerprints.remove(fingerprint);
log.info(
"Fingerprint removed: {}. Total active fingerprints: {}",
fingerprint,
activeFingerprints.size());
}
}
}
public boolean isFingerPrintAllowed(String fingerprint) {
synchronized (activeFingerprints) {
return activeFingerprints.size() < MAX_ACTIVE_FINGERPRINTS
|| activeFingerprints.containsKey(fingerprint);
}
}
public void registerFingerprint(String fingerprint, String sessionId) {
synchronized (activeFingerprints) {
activeFingerprints.put(
fingerprint, new FingerprintInfo(sessionId, System.currentTimeMillis()));
}
}
public void unregisterFingerprint(String fingerprint) {
synchronized (activeFingerprints) {
activeFingerprints.remove(fingerprint);
}
}
@Scheduled(fixedRate = 1800000) // Run every 30 mins
public void cleanupStaleFingerprints() {
log.info("Starting cleanup of stale fingerprints");
long now = System.currentTimeMillis();
int removedCount = 0;
synchronized (activeFingerprints) {
Iterator<Map.Entry<String, FingerprintInfo>> iterator =
activeFingerprints.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, FingerprintInfo> entry = iterator.next();
FingerprintInfo info = entry.getValue();
if (now - info.getLastAccessTime() > FINGERPRINT_EXPIRATION) {
iterator.remove();
removedCount++;
log.info("Removed stale fingerprint: {}", entry.getKey());
}
}
}
log.info("Cleanup complete. Removed {} stale fingerprints", removedCount);
}
public void updateLastAccessTime(String fingerprint) {
FingerprintInfo info = activeFingerprints.get(fingerprint);
if (info != null) {
info.setLastAccessTime(System.currentTimeMillis());
}
}
@Data
@AllArgsConstructor
private static class FingerprintInfo {
private String sessionId;
private long lastAccessTime;
}
}
//package stirling.software.SPDF.config.fingerprint;
//
//import java.util.Iterator;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.concurrent.TimeUnit;
//
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
//import jakarta.servlet.http.HttpSession;
//import jakarta.servlet.http.HttpSessionAttributeListener;
//import jakarta.servlet.http.HttpSessionEvent;
//import jakarta.servlet.http.HttpSessionListener;
//import lombok.AllArgsConstructor;
//import lombok.Data;
//import lombok.extern.slf4j.Slf4j;
//
//@Slf4j
//@Component
//public class FingerprintBasedSessionManager
// implements HttpSessionListener, HttpSessionAttributeListener {
// private static final ConcurrentHashMap<String, FingerprintInfo> activeFingerprints =
// new ConcurrentHashMap<>();
//
// // To be reduced in later version to 8~
// private static final int MAX_ACTIVE_FINGERPRINTS = 30;
//
// static final String STARTUP_TIMESTAMP = "appStartupTimestamp";
// static final long APP_STARTUP_TIME = System.currentTimeMillis();
// private static final long FINGERPRINT_EXPIRATION = TimeUnit.MINUTES.toMillis(30);
//
// @Override
// public void sessionCreated(HttpSessionEvent se) {
// HttpSession session = se.getSession();
// String sessionId = session.getId();
// String fingerprint = (String) session.getAttribute("userFingerprint");
//
// if (fingerprint == null) {
// log.warn("Session created without fingerprint: {}", sessionId);
// return;
// }
//
// synchronized (activeFingerprints) {
// if (activeFingerprints.size() >= MAX_ACTIVE_FINGERPRINTS
// && !activeFingerprints.containsKey(fingerprint)) {
// log.info("Max fingerprints reached. Marking session as blocked: {}", sessionId);
// session.setAttribute("blocked", true);
// } else {
// activeFingerprints.put(
// fingerprint, new FingerprintInfo(sessionId, System.currentTimeMillis()));
// log.info(
// "New fingerprint registered: {}. Total active fingerprints: {}",
// fingerprint,
// activeFingerprints.size());
// }
// session.setAttribute(STARTUP_TIMESTAMP, APP_STARTUP_TIME);
// }
// }
//
// @Override
// public void sessionDestroyed(HttpSessionEvent se) {
// HttpSession session = se.getSession();
// String fingerprint = (String) session.getAttribute("userFingerprint");
//
// if (fingerprint != null) {
// synchronized (activeFingerprints) {
// activeFingerprints.remove(fingerprint);
// log.info(
// "Fingerprint removed: {}. Total active fingerprints: {}",
// fingerprint,
// activeFingerprints.size());
// }
// }
// }
//
// public boolean isFingerPrintAllowed(String fingerprint) {
// synchronized (activeFingerprints) {
// return activeFingerprints.size() < MAX_ACTIVE_FINGERPRINTS
// || activeFingerprints.containsKey(fingerprint);
// }
// }
//
// public void registerFingerprint(String fingerprint, String sessionId) {
// synchronized (activeFingerprints) {
// activeFingerprints.put(
// fingerprint, new FingerprintInfo(sessionId, System.currentTimeMillis()));
// }
// }
//
// public void unregisterFingerprint(String fingerprint) {
// synchronized (activeFingerprints) {
// activeFingerprints.remove(fingerprint);
// }
// }
//
// @Scheduled(fixedRate = 1800000) // Run every 30 mins
// public void cleanupStaleFingerprints() {
// log.info("Starting cleanup of stale fingerprints");
// long now = System.currentTimeMillis();
// int removedCount = 0;
//
// synchronized (activeFingerprints) {
// Iterator<Map.Entry<String, FingerprintInfo>> iterator =
// activeFingerprints.entrySet().iterator();
// while (iterator.hasNext()) {
// Map.Entry<String, FingerprintInfo> entry = iterator.next();
// FingerprintInfo info = entry.getValue();
//
// if (now - info.getLastAccessTime() > FINGERPRINT_EXPIRATION) {
// iterator.remove();
// removedCount++;
// log.info("Removed stale fingerprint: {}", entry.getKey());
// }
// }
// }
//
// log.info("Cleanup complete. Removed {} stale fingerprints", removedCount);
// }
//
// public void updateLastAccessTime(String fingerprint) {
// FingerprintInfo info = activeFingerprints.get(fingerprint);
// if (info != null) {
// info.setLastAccessTime(System.currentTimeMillis());
// }
// }
//
// @Data
// @AllArgsConstructor
// private static class FingerprintInfo {
// private String sessionId;
// private long lastAccessTime;
// }
//}

View File

@ -1,77 +1,77 @@
package stirling.software.SPDF.config.fingerprint;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.springframework.stereotype.Component;
import jakarta.servlet.http.HttpServletRequest;
@Component
public class FingerprintGenerator {
public String generateFingerprint(HttpServletRequest request) {
if (request == null) {
return "";
}
StringBuilder fingerprintBuilder = new StringBuilder();
// Add IP address
fingerprintBuilder.append(request.getRemoteAddr());
// Add X-Forwarded-For header if present (for clients behind proxies)
String forwardedFor = request.getHeader("X-Forwarded-For");
if (forwardedFor != null) {
fingerprintBuilder.append(forwardedFor);
}
// Add User-Agent
String userAgent = request.getHeader("User-Agent");
if (userAgent != null) {
fingerprintBuilder.append(userAgent);
}
// Add Accept-Language header
String acceptLanguage = request.getHeader("Accept-Language");
if (acceptLanguage != null) {
fingerprintBuilder.append(acceptLanguage);
}
// Add Accept header
String accept = request.getHeader("Accept");
if (accept != null) {
fingerprintBuilder.append(accept);
}
// Add Connection header
String connection = request.getHeader("Connection");
if (connection != null) {
fingerprintBuilder.append(connection);
}
// Add server port
fingerprintBuilder.append(request.getServerPort());
// Add secure flag
fingerprintBuilder.append(request.isSecure());
// Generate a hash of the fingerprint
return generateHash(fingerprintBuilder.toString());
}
private String generateHash(String input) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Failed to generate fingerprint hash", e);
}
}
}
//package stirling.software.SPDF.config.fingerprint;
//
//import java.security.MessageDigest;
//import java.security.NoSuchAlgorithmException;
//
//import org.springframework.stereotype.Component;
//
//import jakarta.servlet.http.HttpServletRequest;
//
//@Component
//public class FingerprintGenerator {
//
// public String generateFingerprint(HttpServletRequest request) {
// if (request == null) {
// return "";
// }
// StringBuilder fingerprintBuilder = new StringBuilder();
//
// // Add IP address
// fingerprintBuilder.append(request.getRemoteAddr());
//
// // Add X-Forwarded-For header if present (for clients behind proxies)
// String forwardedFor = request.getHeader("X-Forwarded-For");
// if (forwardedFor != null) {
// fingerprintBuilder.append(forwardedFor);
// }
//
// // Add User-Agent
// String userAgent = request.getHeader("User-Agent");
// if (userAgent != null) {
// fingerprintBuilder.append(userAgent);
// }
//
// // Add Accept-Language header
// String acceptLanguage = request.getHeader("Accept-Language");
// if (acceptLanguage != null) {
// fingerprintBuilder.append(acceptLanguage);
// }
//
// // Add Accept header
// String accept = request.getHeader("Accept");
// if (accept != null) {
// fingerprintBuilder.append(accept);
// }
//
// // Add Connection header
// String connection = request.getHeader("Connection");
// if (connection != null) {
// fingerprintBuilder.append(connection);
// }
//
// // Add server port
// fingerprintBuilder.append(request.getServerPort());
//
// // Add secure flag
// fingerprintBuilder.append(request.isSecure());
//
// // Generate a hash of the fingerprint
// return generateHash(fingerprintBuilder.toString());
// }
//
// private String generateHash(String input) {
// try {
// MessageDigest digest = MessageDigest.getInstance("SHA-256");
// byte[] hash = digest.digest(input.getBytes());
// StringBuilder hexString = new StringBuilder();
// for (byte b : hash) {
// String hex = Integer.toHexString(0xff & b);
// if (hex.length() == 1) hexString.append('0');
// hexString.append(hex);
// }
// return hexString.toString();
// } catch (NoSuchAlgorithmException e) {
// throw new RuntimeException("Failed to generate fingerprint hash", e);
// }
// }
//}