首页 > 解决方案 > Spring Security 5 - 我的自定义 UserDetailsS​​ervice 没有被调用

问题描述

我发现了几个关于类似问题的问题,但没有一个完全是我的情况。

我正在使用以下类在我的应用程序(REST API)中配置身份验证/授权。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .csrf().disable()
            .authorizeRequests()
            .and()
            .exceptionHandling(e -> e
                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
            )
            .antMatcher("/application-api/v1/**").authorizeRequests()
            .antMatchers("/application-api/v1/non-protected").permitAll()
            .anyRequest()
                .authenticated()
            .and()
            .oauth2ResourceServer()
            .opaqueToken();
    }

    @Override
    protected UserDetailsService userDetailsService() {
        return new ApplicationUserDetailsService();
    }
}

无论我尝试什么,我的自定义 ApplicationUserDetailsS​​ervice 都不会被使用。谁能看到这个配置有什么问题?

我还尝试指定以下 bean:

@Service
public class ApplicationUserDetailsService implements UserDetailsService {
    private static final Logger logger = LoggerFactory.getLogger(ApplicationUserDetailsService.class);
    public ApplicationUserDetailsService() {
        logger.debug("Creating instance of ApplicationUserDetailsService");
    }
    @Override
    public UserDetails loadUserByUsername(String userName) {
        logger.debug("Creating user details for {}", userName);

        return new ApplicationUser(userName);
    }
}

它也没有工作。

########### 更新 ###########

我已按如下方式修改了我的 SecurityConfiguration:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);

    @Qualifier("applicationUserDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        logger.info("Oauth2 enabled: {}", enabled);
        httpSecurity.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .csrf().disable()
            .exceptionHandling(e -> e
                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
            )
            .antMatcher("/application-api/v1/**").authorizeRequests()
            .antMatchers("/", "/application-api/unprotected").permitAll()
            .anyRequest()
                .authenticated()
            .and()
            .oauth2ResourceServer()
            .opaqueToken();
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordencoder());
    }

    @Bean(name="passwordEncoder")
    public PasswordEncoder passwordencoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected UserDetailsService userDetailsService() {
        return userDetailsService;
    }
}

我可以看到我的实例已在配置中使用,但它从未被调用。

标签: javaspringspring-security

解决方案


原因可能是因为您正在ApplicationUserDetailsService使用 new 关键字构造它,使其成为非弹簧依赖项

您有 2 个选项,要么使该方法返回UserDetailsService公众并标记为@Bean

@Bean
public UserDetailsService userDetailsService() {
    return new ApplicationUserDetailsService();
}

或者

注入通过或构造函数注入,并在ApplicationUserDetailsService方法中设置对象中的安全服务SecurityConfiguration@AutowiredconfigureHttpSecurity

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);
    private ApplicationUserDetailsService applicationUserDetailsService;
    // inject via constructor
    public SecurityConfig(ApplicationUserDetailsService applicationUserDetailsService) {
        this.applicationUserDetailsService = applicationUserDetailsService;

    }    

    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception 
    {
       httpSecurity.userDetailsService(applicationUserDetailsService);
       .... rest of security config code
    }

推荐阅读