From 8acab77ae32e5d06a40f71d9da43b5a54eb030bf Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 28 Dec 2023 13:50:31 +0000 Subject: [PATCH] contextPath fixes --- .../CustomAuthenticationSuccessHandler.java | 30 ++++++++++++++++-- .../security/SecurityConfiguration.java | 31 +++++++++++++------ .../security/UserAuthenticationFilter.java | 24 ++++++++------ .../api/pipeline/ApiDocService.java | 12 +++++-- .../api/pipeline/PipelineController.java | 11 ++++++- src/main/resources/static/css/home.css | 2 +- src/main/resources/static/js/pipeline.js | 2 +- src/main/resources/templates/account.html | 2 +- .../resources/templates/fragments/navbar.html | 2 +- 9 files changed, 88 insertions(+), 28 deletions(-) diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationSuccessHandler.java b/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationSuccessHandler.java index 7054f084..ae97ec4a 100644 --- a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationSuccessHandler.java +++ b/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationSuccessHandler.java @@ -5,11 +5,13 @@ import java.io.IOException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.stereotype.Component; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; @Component public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { @@ -19,8 +21,32 @@ public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthent @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { - String username = request.getParameter("username"); + String username = request.getParameter("username"); loginAttemptService.loginSucceeded(username); - super.onAuthenticationSuccess(request, response, authentication); + + + // Get the saved request + HttpSession session = request.getSession(false); + SavedRequest savedRequest = session != null ? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST") : null; + if (savedRequest != null && !isStaticResource(savedRequest)) { + // Redirect to the original destination + super.onAuthenticationSuccess(request, response, authentication); + } else { + // Redirect to the root URL (considering context path) + getRedirectStrategy().sendRedirect(request, response, "/"); + } + + //super.onAuthenticationSuccess(request, response, authentication); } + + private boolean isStaticResource(SavedRequest savedRequest) { + String requestURI = savedRequest.getRedirectUrl(); + return requestURI.startsWith("/css/") + || requestURI.startsWith("/js/") + || requestURI.startsWith("/images/") + || requestURI.startsWith("/public/") + || requestURI.startsWith("/pdfjs/") + || requestURI.endsWith(".svg"); + } + } diff --git a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java b/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java index 36526e20..2e78cdd8 100644 --- a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java +++ b/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java @@ -7,6 +7,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.UserDetailsService; @@ -15,12 +16,13 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; +import org.springframework.security.web.savedrequest.NullRequestCache; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import stirling.software.SPDF.repository.JPATokenRepositoryImpl; @Configuration @EnableWebSecurity() -@EnableGlobalMethodSecurity(prePostEnabled = true) +@EnableMethodSecurity public class SecurityConfiguration { @Autowired @@ -41,9 +43,7 @@ public class SecurityConfiguration { @Autowired private UserAuthenticationFilter userAuthenticationFilter; - @Autowired - private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler; - + @Autowired private LoginAttemptService loginAttemptService; @@ -63,11 +63,13 @@ public class SecurityConfiguration { http .formLogin(formLogin -> formLogin .loginPage("/login") - .successHandler(customAuthenticationSuccessHandler) - // .defaultSuccessUrl("/") + .successHandler(new CustomAuthenticationSuccessHandler()) + .defaultSuccessUrl("/") .failureHandler(new CustomAuthenticationFailureHandler(loginAttemptService)) .permitAll() - ) + ).requestCache(requestCache -> requestCache + .requestCache(new NullRequestCache()) + ) .logout(logout -> logout .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/login?logout=true") @@ -79,8 +81,19 @@ public class SecurityConfiguration { .tokenValiditySeconds(1209600) // 2 weeks ) .authorizeHttpRequests(authz -> authz - .requestMatchers(req -> req.getRequestURI().startsWith("/login") || req.getRequestURI().endsWith(".svg") || req.getRequestURI().startsWith("/register") || req.getRequestURI().startsWith("/error") || req.getRequestURI().startsWith("/images/") || req.getRequestURI().startsWith("/public/") || req.getRequestURI().startsWith("/css/") || req.getRequestURI().startsWith("/js/")) - .permitAll() + .requestMatchers(req -> { + String uri = req.getRequestURI(); + String contextPath = req.getContextPath(); + + // Remove the context path from the URI + String trimmedUri = uri.startsWith(contextPath) ? uri.substring(contextPath.length()) : uri; + + return trimmedUri.startsWith("/login") || trimmedUri.endsWith(".svg") || + trimmedUri.startsWith("/register") || trimmedUri.startsWith("/error") || + trimmedUri.startsWith("/images/") || trimmedUri.startsWith("/public/") || + trimmedUri.startsWith("/css/") || trimmedUri.startsWith("/js/"); + } + ).permitAll() .anyRequest().authenticated() ) .userDetailsService(userDetailsService) diff --git a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java index d13cce7c..ce77e5a4 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java @@ -74,8 +74,10 @@ public class UserAuthenticationFilter extends OncePerRequestFilter { // If we still don't have any authentication, deny the request if (authentication == null || !authentication.isAuthenticated()) { String method = request.getMethod(); - if ("GET".equalsIgnoreCase(method) && !"/login".equals(requestURI)) { - response.sendRedirect("/login"); // redirect to the login page + String contextPath = request.getContextPath(); + + if ("GET".equalsIgnoreCase(method) && ! (contextPath + "/login").equals(requestURI)) { + response.sendRedirect(contextPath + "/login"); // redirect to the login page return; } else { response.setStatus(HttpStatus.UNAUTHORIZED.value()); @@ -90,15 +92,17 @@ public class UserAuthenticationFilter extends OncePerRequestFilter { @Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { String uri = request.getRequestURI(); - + String contextPath = request.getContextPath(); String[] permitAllPatterns = { - "/login", - "/register", - "/error", - "/images/", - "/public/", - "/css/", - "/js/" + contextPath + "/login", + contextPath + "/register", + contextPath + "/error", + contextPath + "/images/", + contextPath + "/public/", + contextPath + "/css/", + contextPath + "/js/", + contextPath + "/pdfjs/", + contextPath + "/site.webmanifest" }; for (String pattern : permitAllPatterns) { diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java index 6529c932..8ceaaa76 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java @@ -15,14 +15,22 @@ import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletContext; import stirling.software.SPDF.model.ApiEndpoint; import stirling.software.SPDF.model.Role; @Service public class ApiDocService { private final Map apiDocumentation = new HashMap<>(); - private final String apiDocsUrl = "http://localhost:8080/v1/api-docs"; // URL to your API documentation + @Autowired + private ServletContext servletContext; + + private String getApiDocsUrl() { + String contextPath = servletContext.getContextPath(); + return "http://localhost:8080" + contextPath + "/v1/api-docs"; + } + @Autowired(required=false) private UserServiceInterface userService; @@ -44,7 +52,7 @@ public class ApiDocService { HttpEntity entity = new HttpEntity<>(headers); RestTemplate restTemplate = new RestTemplate(); - ResponseEntity response = restTemplate.exchange(apiDocsUrl, HttpMethod.GET, entity, String.class); + ResponseEntity response = restTemplate.exchange(getApiDocsUrl(), HttpMethod.GET, entity, String.class); String apiDocsJson = response.getBody(); ObjectMapper mapper = new ObjectMapper(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java index a211d379..47954026 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java @@ -50,6 +50,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.ServletContext; import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.PipelineConfig; import stirling.software.SPDF.model.PipelineOperation; @@ -117,6 +118,14 @@ public class PipelineController { return userService.getApiKeyForUser(Role.INTERNAL_API_USER.getRoleId()); } + @Autowired + private ServletContext servletContext; + + private String getBaseUrl() { + String contextPath = servletContext.getContextPath(); + return "http://localhost:8080" + contextPath + "/"; + } + private void handleDirectory(Path dir) throws Exception { logger.info("Handling directory: {}", dir); @@ -337,7 +346,7 @@ public class PipelineController { HttpEntity> entity = new HttpEntity<>(body, headers); RestTemplate restTemplate = new RestTemplate(); - String url = "http://localhost:8080/" + operation; + String url = getBaseUrl() + operation; ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, entity, byte[].class); diff --git a/src/main/resources/static/css/home.css b/src/main/resources/static/css/home.css index ab3b3348..fe184637 100644 --- a/src/main/resources/static/css/home.css +++ b/src/main/resources/static/css/home.css @@ -1,5 +1,5 @@ #searchBar { - background-image: url('/images/search.svg'); + background-image: url('../images/search.svg'); background-position: 16px 16px; background-repeat: no-repeat; width: 100%; diff --git a/src/main/resources/static/js/pipeline.js b/src/main/resources/static/js/pipeline.js index ea073f6f..4fcde3a0 100644 --- a/src/main/resources/static/js/pipeline.js +++ b/src/main/resources/static/js/pipeline.js @@ -130,7 +130,7 @@ document.getElementById('submitConfigBtn').addEventListener('click', function() formData.append('json', pipelineConfigJson); console.log("formData", formData); - fetch('/api/v1/pipeline/handleData', { + fetch('api/v1/pipeline/handleData', { method: 'POST', body: formData }) diff --git a/src/main/resources/templates/account.html b/src/main/resources/templates/account.html index 83303057..c0e7a757 100644 --- a/src/main/resources/templates/account.html +++ b/src/main/resources/templates/account.html @@ -306,7 +306,7 @@