AuthenticationManager.authenticate() 返回 stackoverflow

问题描述 投票:0回答:1

我正在尝试在我的项目上制作一个简单的登录系统,也使用 Spring 3.1.1 和 Spring Security 3.1.1。阅读文档,我们不应该再“扩展 WebSecurityAdapter”,而是像这样实现它:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    RequestFilter requestFilter;

    /**
     * List with whitelisted endpoints.
     */
    private static final String[] AUTH_WHITELIST = {
            // -- Swagger UI v2
            "/v2/api-docs",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/swagger-ui.html",
            "/webjars/**",
            // -- Swagger UI v3 (OpenAPI)
            "/v3/api-docs/**",
            "/swagger-ui/**",
            // other public endpoints of your API may be appended to this array
            "/users/register",
            "/users/login",
            "/plans/free-plan"
    };

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(AUTH_WHITELIST).permitAll()
                        .anyRequest().authenticated()
                )
                .addFilterBefore(requestFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return web -> web.ignoring().requestMatchers("/v3/api-docs/**");
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

在这个类中,我在 bean 上创建了一个“AuthenticationManager”,但是当我尝试在我的服务上使用它时,它会出现 Stackoverflow 错误。我的服务:

@Service
public class UserService extends GenericService<User> {

    /**
     * Authentication Manager instance.
     */
    private final AuthenticationManager authenticationManager;

    /**
     * User Repository instance.
     */
    private final UserRepository userRepository;

    /**
     * JWTUtils Instance.
     */
    private JWTTokenUtils jwtTokenUtils;

    /**
     * Plan Service instance.
     */
    private PlanService planService;

    @Autowired
    public UserService(AuthenticationManager authenticationManager, UserRepository userRepository,
                       JWTTokenUtils jwtTokenUtils, PlanService planService) {
        this.authenticationManager = authenticationManager;
        this.userRepository = userRepository;
        this.jwtTokenUtils = jwtTokenUtils;
        this.planService = planService;
    }

    @Override
    protected GenericRepository getGenericRepository() {
        return userRepository;
    }

    @Override
    protected SearchPredicate<User> getSearchPredicate(String search) {
        return null;
    }

    /* Methods */

    /**
     * Method to login on Coupler API.
     *
     * @param jwtRequestDTO Login request DTO.
     * @return {@link JwtResponseDTO}. JWT Token with all the info.
     * @throws RestRequestException The API can throw an exception if it cannot find necessary data.
     */
    public JwtResponseDTO login(JwtRequestDTO jwtRequestDTO) throws RestRequestException {
        var userPassword = new UsernamePasswordAuthenticationToken(jwtRequestDTO.getEmail(), jwtRequestDTO.getPassword());
        // The error is here!
        var auth = authenticationManager.authenticate(userPassword);
        var token = jwtTokenUtils.generateToken(((User) auth.getPrincipal()).getEmail());
        User user = userRepository.findByEmail(jwtRequestDTO.getEmail())
                .orElseThrow(() -> new RestRequestException(HttpStatus.NOT_FOUND, ErrorIndicator.FIM_ERROR_U01.getMessage()));
        return new JwtResponseDTO(token, user.getId());
    }
}

我没有在系统中定义任何其他 AuthenticationManager,当我用 AuthenticationManager 注释或删除“@Bean”时,它声称我的 UserService 需要一个未提供的 bean,而该光束就是 AuthenticationManager。 “RequestFilter”是我的“扩展的 OncePerRequestFilter”实现,不认为存在问题,所以为了保持简单,我将忽略它。

java spring security spring-security
1个回答
0
投票

这是一个已知问题。您可以正确发布

AuthenticationManager
bean 来解决它。例如,请参阅此评论此博客文章此答案5.8 迁移指南

请注意,Spring Security 也具有对 JWT 的内置支持,因此您可以避免编写自己的过滤器。

© www.soinside.com 2019 - 2024. All rights reserved.