mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-05-23 10:22:01 +00:00
clean up and more
This commit is contained in:
parent
e76e83c427
commit
4ed49d0c15
src/main
@ -151,10 +151,10 @@ public class EndpointInterceptor implements HandlerInterceptor {
|
||||
if ((userSessions >= maxUserSessions
|
||||
|| totalSessionsNonExpired >= maxApplicationSessions)
|
||||
&& !hasUserActiveSession) {
|
||||
response.sendError(
|
||||
HttpServletResponse.SC_UNAUTHORIZED,
|
||||
log.info(
|
||||
"Max sessions reached for this user. To continue on this device, please"
|
||||
+ " close your session in another browser.");
|
||||
response.sendError(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -203,10 +203,10 @@ public class EndpointInterceptor implements HandlerInterceptor {
|
||||
|
||||
if (totalSessions >= maxApplicationSessions && !hasUserActiveSession) {
|
||||
sessionsInterface.removeSession(finalSession);
|
||||
response.sendError(
|
||||
HttpServletResponse.SC_UNAUTHORIZED,
|
||||
log.info(
|
||||
"Max sessions reached for this user. To continue on this device, please"
|
||||
+ " close your session in another browser.");
|
||||
response.sendError(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return false;
|
||||
}
|
||||
if (!hasUserActiveSession) {
|
||||
|
@ -193,8 +193,15 @@ public class AnonymusSessionListener implements HttpSessionListener, SessionsInt
|
||||
@Override
|
||||
public void removeSession(HttpSession session) {
|
||||
AnonymusSessionInfo sessionsInfo = (AnonymusSessionInfo) sessions.get(session.getId());
|
||||
sessionsInfo.setExpired(true);
|
||||
session.invalidate();
|
||||
if (sessionsInfo != null) {
|
||||
sessionsInfo.setExpired(true);
|
||||
}
|
||||
try {
|
||||
session.invalidate();
|
||||
} catch (IllegalStateException e) {
|
||||
log.debug("Session {} already invalidated", session.getId());
|
||||
}
|
||||
sessions.remove(session.getId());
|
||||
sessions.remove(session.getId());
|
||||
}
|
||||
|
||||
|
87
src/main/java/stirling/software/SPDF/config/anonymus/session/AnonymusSessionStatusController.java
87
src/main/java/stirling/software/SPDF/config/anonymus/session/AnonymusSessionStatusController.java
@ -1,9 +1,10 @@
|
||||
package stirling.software.SPDF.config.anonymus.session;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
@ -12,72 +13,44 @@ import jakarta.servlet.http.HttpSession;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.SPDF.config.interfaces.SessionsModelInterface;
|
||||
|
||||
@Controller
|
||||
@Slf4j
|
||||
public class AnonymusSessionStatusController {
|
||||
|
||||
@Autowired private AnonymusSessionListener sessionRegistry;
|
||||
|
||||
@GetMapping("/session/status")
|
||||
public ResponseEntity<String> getSessionStatus(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) {
|
||||
// No session found
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("No session found");
|
||||
}
|
||||
|
||||
boolean isActiveSession =
|
||||
sessionRegistry.getAllSessions().stream()
|
||||
.filter(s -> s.getSessionId().equals(session.getId()))
|
||||
.anyMatch(s -> !s.isExpired());
|
||||
|
||||
long sessionCount =
|
||||
sessionRegistry.getAllSessions().stream().filter(s -> !s.isExpired()).count();
|
||||
|
||||
long userSessions = sessionCount;
|
||||
int maxUserSessions = sessionRegistry.getMaxUserSessions();
|
||||
|
||||
// Session invalid or expired
|
||||
if (userSessions >= maxUserSessions && !isActiveSession) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||
.body("Session invalid or expired");
|
||||
}
|
||||
// Valid session
|
||||
else if (session.getId() != null && isActiveSession) {
|
||||
return ResponseEntity.ok("Valid session: " + session.getId());
|
||||
}
|
||||
// Fallback message with session count
|
||||
else {
|
||||
return ResponseEntity.ok("User has " + userSessions + " sessions");
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/session/expire")
|
||||
public String expireSession(HttpServletRequest request) {
|
||||
@GetMapping("/userSession")
|
||||
public String getUserSessions(HttpServletRequest request, Model model) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
// Invalidate current session
|
||||
sessionRegistry.expireFirstSession(session.getId());
|
||||
log.info("Session invalidated: {}", session.getId());
|
||||
// return ResponseEntity.ok("Session invalidated");
|
||||
} else {
|
||||
log.info("No session to invalidate");
|
||||
// return ResponseEntity.ok("No session to invalidate");
|
||||
|
||||
boolean isSessionValid =
|
||||
sessionRegistry.getAllNonExpiredSessions().stream()
|
||||
.allMatch(
|
||||
sessionEntity ->
|
||||
sessionEntity.getSessionId().equals(session.getId()));
|
||||
|
||||
// Get all sessions for the user
|
||||
List<SessionsModelInterface> sessionList =
|
||||
sessionRegistry.getAllNonExpiredSessions().stream()
|
||||
.filter(
|
||||
sessionEntity ->
|
||||
!sessionEntity.getSessionId().equals(session.getId()))
|
||||
.toList();
|
||||
|
||||
model.addAttribute("sessionList", sessionList);
|
||||
return "userSession";
|
||||
}
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
@GetMapping("/session/expire/all")
|
||||
public ResponseEntity<String> expireAllSessions() {
|
||||
// Invalidate all sessions
|
||||
sessionRegistry.expireAllSessions();
|
||||
return ResponseEntity.ok("All sessions invalidated");
|
||||
}
|
||||
|
||||
@GetMapping("/session/expire/{username}")
|
||||
public ResponseEntity<String> expireAllSessionsByUsername(@PathVariable String username) {
|
||||
// Invalidate all sessions for specific user
|
||||
sessionRegistry.expireAllSessionsByUsername(username);
|
||||
return ResponseEntity.ok("All sessions invalidated for user: " + username);
|
||||
@GetMapping("/userSession/invalidate/{sessionId}")
|
||||
public String invalidateUserSession(
|
||||
HttpServletRequest request, @PathVariable String sessionId) {
|
||||
sessionRegistry.expireSession(sessionId);
|
||||
sessionRegistry.registerSession(request.getSession(false));
|
||||
return "redirect:/userSession";
|
||||
}
|
||||
}
|
||||
|
@ -142,25 +142,25 @@ public class CustomHttpSessionListener implements HttpSessionListener, SessionsI
|
||||
.filter(s -> !s.isExpired() && s.getPrincipalName().equals(principalName))
|
||||
.toList()
|
||||
.size();
|
||||
boolean isAnonymousUserWithoutLogin = "anonymousUser".equals(principalName) && loginEnabled;
|
||||
boolean isAnonymousUserWithLogin = "anonymousUser".equals(principalName) && loginEnabled;
|
||||
log.info(
|
||||
"all {} allNonExpiredSessions {} {} isAnonymousUserWithoutLogin {}",
|
||||
"all {} allNonExpiredSessions {} {} isAnonymousUserWithLogin {}",
|
||||
all,
|
||||
allNonExpiredSessions,
|
||||
getMaxUserSessions(),
|
||||
isAnonymousUserWithoutLogin);
|
||||
isAnonymousUserWithLogin);
|
||||
|
||||
if (allNonExpiredSessions >= getMaxApplicationSessions() && !isAnonymousUserWithoutLogin) {
|
||||
if (allNonExpiredSessions >= getMaxApplicationSessions() && !isAnonymousUserWithLogin) {
|
||||
log.info("Session {} Expired=TRUE", session.getId());
|
||||
sessionPersistentRegistry.expireSession(session.getId());
|
||||
sessionPersistentRegistry.removeSessionInformation(se.getSession().getId());
|
||||
// if (allNonExpiredSessions > getMaxUserSessions()) {
|
||||
// enforceMaxSessionsForPrincipal(principalName);
|
||||
// }
|
||||
} else if (all >= getMaxUserSessions() && !isAnonymousUserWithoutLogin) {
|
||||
} else if (all >= getMaxUserSessions() && !isAnonymousUserWithLogin) {
|
||||
enforceMaxSessionsForPrincipal(principalName);
|
||||
log.info("Session {} Expired=TRUE", session.getId());
|
||||
} else if (isAnonymousUserWithoutLogin) {
|
||||
} else if (isAnonymousUserWithLogin) {
|
||||
sessionPersistentRegistry.expireSession(session.getId());
|
||||
sessionPersistentRegistry.removeSessionInformation(se.getSession().getId());
|
||||
} else {
|
||||
|
@ -3,11 +3,8 @@ package stirling.software.SPDF.config.anonymus.session;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@ -29,35 +26,32 @@ import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||
@Slf4j
|
||||
public class SessionStatusController {
|
||||
|
||||
@Qualifier("loginEnabled")
|
||||
private boolean loginEnabled;
|
||||
|
||||
@Autowired private SessionPersistentRegistry sessionPersistentRegistry;
|
||||
@Autowired private SessionsInterface sessionInterface;
|
||||
|
||||
@Autowired private CustomHttpSessionListener customHttpSessionListener;
|
||||
|
||||
// Returns the current session ID or 401 if no session exists
|
||||
@GetMapping("/session")
|
||||
public ResponseEntity<String> getSession(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("No session found");
|
||||
} else {
|
||||
return ResponseEntity.ok(session.getId());
|
||||
}
|
||||
}
|
||||
|
||||
// list all sessions from authentication user, return String redirect userSession.html
|
||||
@GetMapping("/userSession")
|
||||
public String getUserSessions(
|
||||
HttpServletRequest request, Model model, Authentication authentication) {
|
||||
if (authentication == null || !authentication.isAuthenticated()) {
|
||||
if ((authentication == null || !authentication.isAuthenticated()) && loginEnabled) {
|
||||
return "redirect:/login";
|
||||
}
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
String principalName = UserUtils.getUsernameFromPrincipal(principal);
|
||||
if (principalName == null) {
|
||||
return "redirect:/login";
|
||||
String principalName = null;
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
principalName = UserUtils.getUsernameFromPrincipal(principal);
|
||||
if (principalName == null) {
|
||||
return "redirect:/login";
|
||||
}
|
||||
} else {
|
||||
principalName = "anonymousUser";
|
||||
}
|
||||
|
||||
boolean isSessionValid =
|
||||
@ -139,81 +133,4 @@ public class SessionStatusController {
|
||||
return "redirect:/login";
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if the session is active and valid according to user session limits
|
||||
@GetMapping("/session/status")
|
||||
public ResponseEntity<String> getSessionStatus(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
Object principalTest = authentication.getPrincipal();
|
||||
String username = UserUtils.getUsernameFromPrincipal(principalTest);
|
||||
|
||||
List<SessionInformation> allSessions =
|
||||
sessionPersistentRegistry.getAllSessions(username, false);
|
||||
|
||||
boolean isActivSession =
|
||||
sessionPersistentRegistry.getAllSessions().stream()
|
||||
.filter(
|
||||
sessionEntity ->
|
||||
session.getId().equals(sessionEntity.getSessionId()))
|
||||
.anyMatch(sessionEntity -> !sessionEntity.isExpired());
|
||||
|
||||
int userSessions = allSessions.size();
|
||||
int maxUserSessions = sessionInterface.getMaxUserSessions();
|
||||
|
||||
// Check if the current session is valid or expired based on the session registry
|
||||
if (userSessions >= maxUserSessions && !isActivSession) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||
.body("Session invalid or expired");
|
||||
} else if (session.getId() != null && isActivSession) {
|
||||
return ResponseEntity.ok("Valid session: " + session.getId());
|
||||
} else {
|
||||
return ResponseEntity.ok(
|
||||
"User: " + username + " has " + userSessions + " sessions");
|
||||
}
|
||||
} else {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||
.body("Session invalid or expired");
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidates the current session
|
||||
@GetMapping("/session/expire")
|
||||
public ResponseEntity<String> expireSession(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
sessionPersistentRegistry.expireSession(session.getId());
|
||||
return ResponseEntity.ok("Session invalidated");
|
||||
} else {
|
||||
return ResponseEntity.ok("No session to invalidate");
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidates all sessions
|
||||
@GetMapping("/session/expire/all")
|
||||
public ResponseEntity<String> expireAllSessions() {
|
||||
log.debug("Expire all sessions");
|
||||
sessionPersistentRegistry.expireAllSessions();
|
||||
return ResponseEntity.ok("All sessions invalidated");
|
||||
}
|
||||
|
||||
// Invalidates all sessions for a specific user, only if requested by the same user
|
||||
@GetMapping("/session/expire/{username}")
|
||||
public ResponseEntity<String> expireAllSessionsByUsername(@PathVariable String username) {
|
||||
SecurityContext cxt = SecurityContextHolder.getContext();
|
||||
Authentication auth = cxt.getAuthentication();
|
||||
if (auth != null && auth.isAuthenticated()) {
|
||||
Object principal = auth.getPrincipal();
|
||||
String principalName = UserUtils.getUsernameFromPrincipal(principal);
|
||||
if (principalName.equals(username)) {
|
||||
sessionPersistentRegistry.expireAllSessionsByUsername(username);
|
||||
return ResponseEntity.ok("All sessions invalidated for user: " + username);
|
||||
} else {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized");
|
||||
}
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized");
|
||||
}
|
||||
}
|
||||
|
@ -287,6 +287,14 @@ database.notSupported=Diese Funktion ist für deine Datenbankverbindung nicht ve
|
||||
session.expired=Ihre Sitzung ist abgelaufen. Bitte laden Sie die Seite neu und versuchen Sie es erneut.
|
||||
session.refreshPage=Seite aktualisieren
|
||||
|
||||
#################
|
||||
# USER SESSION #
|
||||
#################
|
||||
userSession.title=Benutzersitzungen
|
||||
userSession.header=Benutzersitzungen
|
||||
userSession.maxUserSession=Wenn die maximale Anzahl Sitzungen für diesen Benutzer erreicht ist, können Sie hier andere Anmeldungen beenden, um auf diesem Gerät fortzufahren.
|
||||
userSession.lastRequest=Letzte Aufrufe
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
|
@ -287,6 +287,14 @@ database.notSupported=This function is not available for your database connectio
|
||||
session.expired=Your session has expired. Please refresh the page and try again.
|
||||
session.refreshPage=Refresh Page
|
||||
|
||||
#################
|
||||
# USER SESSION #
|
||||
#################
|
||||
userSession.title=User Sessions
|
||||
userSession.header=User Sessions
|
||||
userSession.maxUserSession=If the maximum number of sessions for this user is reached, you can end other logins here to continue on this device.
|
||||
userSession.lastRequest=last Request
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
|
@ -15,8 +15,7 @@
|
||||
<p class="lead" th:if="${param.status == '404'}" th:text="#{error.404.1}"></p>
|
||||
<p class="lead" th:unless="${param.status == '404'}" th:text="#{error.404.2}"></p>
|
||||
<p class="lead" th:if="${status == 417}">
|
||||
<a th:href="@{'/userSession'}" th:text="#{session.maxUserSession}">Max sessions reached for this user. To continue on this device, please close your
|
||||
session in another browser.</a>
|
||||
<a th:href="@{'/userSession'}" th:text="#{userSession.maxUserSession}">Max sessions reached for this user.</a>
|
||||
</p>
|
||||
<br>
|
||||
<h2 th:text="#{error.needHelp}"></h2>
|
||||
|
@ -3,7 +3,7 @@
|
||||
xmlns:th="https://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{session.title}, header=#{session.header})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{userSession.title}, header=#{userSession.header})}"></th:block>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -16,21 +16,21 @@
|
||||
<div class="col-md-9 bg-card">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon organize">key</span>
|
||||
<span class="tool-header-text" th:text="#{session.user}">User Session</span>
|
||||
<span class="tool-header-text" th:text="#{userSession.title}">User Session</span>
|
||||
</div>
|
||||
<div class="bg-card mt-3 mb-3">
|
||||
<span th:text="#{session.maxUserSession}">Max sessions reached for this user. To continue on this device, please close your session in another browser.</span>
|
||||
<table class="table table-striped table-hover mb-0">
|
||||
<span th:text="#{userSession.maxUserSession}">Max sessions reached for this user.</span>
|
||||
<table th:unless="${#lists.isEmpty(sessionList)}" class="table table-striped table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" th:text="#{session.sessionId}">Session ID</th>
|
||||
<th scope="col" th:text="#{session.lastRequest}">last Request</th>
|
||||
<th scope="col" th:text="#{session.invalidate}">Logout</th>
|
||||
<!-- <th scope="col" th:text="#{session.sessionId}">Session ID</th> -->
|
||||
<th scope="col" th:text="#{userSession.lastRequest}">last Request</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="userSession : ${sessionList}">
|
||||
<td th:text="${userSession.getSessionId}"></td>
|
||||
<!-- <td th:text="${userSession.getSessionId}"></td> -->
|
||||
<td th:text="${userSession.getLastRequest}"></td>
|
||||
<td><a th:href="@{/userSession/invalidate/{id}(id=${userSession.getSessionId})}"
|
||||
class="btn btn-sm btn-danger">
|
||||
|
Loading…
x
Reference in New Issue
Block a user