From 15c73d9dd3d1449746f9f578729b42dd18c161d4 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Tue, 15 Aug 2023 00:40:22 +0100 Subject: [PATCH] Add files via upload --- .../security/UserAuthenticationFilter.java | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java diff --git a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java new file mode 100644 index 00000000..d7d40710 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java @@ -0,0 +1,120 @@ +package stirling.software.SPDF.config.security; + +import java.io.IOException; +import java.time.Duration; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Lazy; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import io.github.bucket4j.Bandwidth; +import io.github.bucket4j.Bucket; +import io.github.bucket4j.Bucket4j; +import io.github.bucket4j.ConsumptionProbe; +import io.github.bucket4j.Refill; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import stirling.software.SPDF.model.ApiKeyAuthenticationToken; +@Component +public class UserAuthenticationFilter extends OncePerRequestFilter { + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + @Lazy + private UserService userService; + + + @Autowired + @Qualifier("loginEnabled") + public boolean loginEnabledValue; + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + if (!loginEnabledValue) { + // If login is not enabled, just pass all requests without authentication + filterChain.doFilter(request, response); + return; + } + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + // Check for API key in the request headers if no authentication exists + if (authentication == null || !authentication.isAuthenticated()) { + String apiKey = request.getHeader("X-API-Key"); + if (apiKey != null && !apiKey.trim().isEmpty()) { + try { + // Use API key to authenticate. This requires you to have an authentication provider for API keys. + UserDetails userDetails = userService.loadUserByApiKey(apiKey); + if(userDetails == null) + { + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.getWriter().write("Invalid API Key."); + return; + } + authentication = new ApiKeyAuthenticationToken(userDetails, apiKey, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + } catch (AuthenticationException e) { + // If API key authentication fails, deny the request + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.getWriter().write("Invalid API Key."); + return; + } + } + } + + // If we still don't have any authentication, deny the request + if (authentication == null || !authentication.isAuthenticated()) { + String method = request.getMethod(); + if ("GET".equalsIgnoreCase(method)) { + response.sendRedirect("/login"); // redirect to the login page + return; + } + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.getWriter().write("Authentication required. Please provide a X-API-KEY in request header.\nThis is found in Settings -> Account Settings -> API Key\nAlternativly you can disable authentication if this is unexpected"); + return; + } + + filterChain.doFilter(request, response); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + String uri = request.getRequestURI(); + + String[] permitAllPatterns = { + "/login", + "/register", + "/error", + "/images/", + "/public/", + "/css/", + "/js/" + }; + + for (String pattern : permitAllPatterns) { + if (uri.startsWith(pattern) || uri.endsWith(".svg")) { + return true; + } + } + + return false; + } + +}