最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

java - NoResourceFoundException in Spring Boot Oauth flow after spring boot 3 upgrade - Stack Overflow

matteradmin4PV0评论

I've recently upgraded spring boot from 2.x.x version to 3.3.3 and spring security v.6.4.3 and faced an issue when calling my /api/v1/authentication/login endpoint. When the user is authenticated with oauth2 and should be redirected to the endpoint, a NoResourceFoundException is thrown. For some reason DispatcherServlet is classyfing the request as a request for a static resource, instead of a dynamic endpoint. I'm attaching related logs below.

This endpoint is oauth protected and defined as

@Slf4j
@Validated
@RestController
@Tag(name = "Authentication")
@RequestMapping("/api/v1/authentication")
public class AuthenticationControllerBase {

    protected final UserService userService;
    private final ObjectMapper objectMapper;

    public AuthenticationControllerBase(UserService userService, ObjectMapper objectMapper) {
        log.info("Initializing AuthenticationControllerBase");
        this.userService = userService;
        this.objectMapper = objectMapper;
    }

    @PostMapping(value = "/login")
    public LoginResponse login(@AuthenticationPrincipal OidcUser principal) throws StatusManagementException {
        String email = principal.getUserInfo().getEmail();
        email = EmailUtil.normalizeEmail(email);
        User user = userService.getUser(email);
        return user.getRole() == UserRole.APPLICATION_ADMIN
                ? userService.loginWithLock(email)
                : userService.loginWithoutLock(email);
    }
}

My Security configuration is

package com.kyc.service.config;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import .springframework.beans.factory.annotation.Value;
import .springframework.context.annotation.Bean;
import .springframework.context.annotation.Configuration;
import .springframework.context.annotation.Profile;
import .springframework.security.config.annotation.web.builders.HttpSecurity;
import .springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import .springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import .springframework.security.web.SecurityFilterChain;
import .springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import .springframework.security.web.session.InvalidSessionStrategy;
import .springframework.security.web.session.SessionInformationExpiredEvent;
import .springframework.security.web.session.SessionInformationExpiredStrategy;
import .springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.io.IOException;


@Slf4j
@Configuration
@Profile({"pl-demo", "pl-stage"})
@RequiredArgsConstructor
@EnableWebSecurity
public class OIDCSecurityConfigurationPl {

    @Value("${service.configuration.oidc.auth-redirection-uri}")
    private String authorizeRedirectionURI;
    @Value("${service.configuration.oidc.logout-redirection-url}")
    private String logoutRedirectionURL;
    @Value("${service.configuration.oidc.logout-uri}")
    private String logoutURI;

    private final SessionAuthenticationStrategy sessionAuthenticationStrategy;

    @Bean
    protected SecurityFilterChain configure(HttpSecurity http) {

        try {
            http.csrf(AbstractHttpConfigurer::disable);
            http.cors(AbstractHttpConfigurer::disable);
            http.authorizeHttpRequests(authorizeRequests -> authorizeRequests.requestMatchers("/", "/error", "/actuator/health",
                            "/oauth2/authorization/**", "/api/v1/identity-verification/webhook",
                            "/api/v1/engagements/*/export/*/pdf")
                    .permitAll()
                    .anyRequest()
                    .authenticated());
            setupOauth(http);
            http.sessionManagement(sess -> sess.sessionAuthenticationStrategy(sessionAuthenticationStrategy)
                    .requireExplicitAuthenticationStrategy(false)
                    .invalidSessionStrategy(new KYCSessionExpirationStrategy()).maximumSessions(1));
            http.logout(logout -> logout.logoutRequestMatcher(new AntPathRequestMatcher(logoutURI))
                    .invalidateHttpSession(true)
                    .logoutSuccessUrl(logoutRedirectionURL));
            return http.build();
        } catch (Exception e) {
            log.error("Exception in OIDC configuration", e);
            throw new SecurityException(e);
        }
    }

    private void setupOauth(HttpSecurity http) {
        try {
            http.oauth2Login(oauth -> oauth.redirectionEndpoint(redir -> redir.baseUri(authorizeRedirectionURI)));
        } catch (Exception e) {
            log.error("oauth2Login:: Exception in oauth2Login configuration", e);
        }
    }

    private static class KYCSessionExpirationStrategy implements SessionInformationExpiredStrategy, InvalidSessionStrategy {

        @Override
        public void onExpiredSessionDetected(SessionInformationExpiredEvent sessionInformationExpiredEvent)
                throws IOException {
            sessionInformationExpiredEvent.getResponse().sendError(HttpServletResponse.SC_UNAUTHORIZED);
        }

        @Override
        public void onInvalidSessionDetected(HttpServletRequest httpServletRequest,
                                             HttpServletResponse httpServletResponse)
                throws IOException {
            log.info("invalid session...");
            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
}
2025-04-03 15:36:00 
.springframework.web.servlet.resource.NoResourceFoundException: No static resource api/v1/authentication/login.
2025-04-03 15:36:00 
2025-04-03 13:36:00.546 ERROR 31 ---    34 [  XNIO-1 task-2] c.p.k.s.a.e.GlobalExceptionHandler       : Internal server error 
2025-04-03 15:36:00 
2025-04-03 13:36:00.546 DEBUG 31 ---    34 [  XNIO-1 task-2] .m.m.a.ExceptionHandlerExceptionResolver : Using @ExceptionHandler com.pwc.kyc.service.api.exception.GlobalExceptionHandler#handleAll(Exception) 
2025-04-03 15:36:00 
2025-04-03 13:36:00.545 DEBUG 31 ---    34 [  XNIO-1 task-2] o.s.w.s.r.ResourceHttpRequestHandler     : Resource not found 
2025-04-03 15:36:00 
2025-04-03 13:36:00.542 DEBUG 31 ---    34 [  XNIO-1 task-2] o.s.w.s.h.SimpleUrlHandlerMapping        : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]] 
2025-04-03 15:36:00 
2025-04-03 13:36:00.541 DEBUG 31 ---    34 [  XNIO-1 task-2] o.s.w.s.DispatcherServlet                : POST "/stage/api/v1/authentication/login/", parameters={} 
2025-04-03 15:36:00 
2025-04-03 13:36:00.540 DEBUG 31 ---    34 [  XNIO-1 task-2] c.p.k.s.c.f.ConcurrentAdminSessionFilter : All sessions det size: 1 
2025-04-03 15:36:00 
2025-04-03 13:36:00.540 DEBUG 31 ---    34 [  XNIO-1 task-2] c.p.k.s.c.f.ConcurrentAdminSessionFilter : All principals size: 1 
2025-04-03 15:36:00 
2025-04-03 13:36:00.531 DEBUG 31 ---    34 [  XNIO-1 task-2] tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation 
2025-04-03 15:36:00 
2025-04-03 13:36:00.529 DEBUG 31 ---    34 [  XNIO-1 task-2] o.s.s.w.FilterChainProxy                 : Secured POST /api/v1/authentication/login/ 
2025-04-03 15:36:00 
2025-04-03 13:36:00.528 DEBUG 31 ---    34 [  XNIO-1 task-2] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=OAuth2AuthenticationToken [PROTECTED]]
Post a comment

comment list (0)

  1. No comments so far