繁体   English   中英

Spring 安全 5 - 我的自定义 UserDetailsService 未被调用

[英]Spring Security 5 - My custom UserDetailsService is not called

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

我正在使用以下 class 在我的应用程序中配置身份验证/授权(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();
    }
}

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

我还尝试指定以下 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;
    }
}

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

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

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

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

或者

通过@Autowired或构造函数注入在SecurityConfiguration中注入ApplicationUserDetailsService ervice,并在configure方法中设置HttpSecurity object 中的安全服务

@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
    }

这可能是 bean 创建顺序的情况。 可能是在创建 SecurityConfiguration 时 applicationUserDetailsService bean 不可用于自动装配。 您可以尝试在 SecurityConfiguration 上添加@dependson并查看是否有效。

您正在配置中注入 UserDetailService 。 UserDetailsServiceAutoConfiguration 默认来自 Spring。

@Autowired
private UserDetailsService userDetailsService;

代替 userDetailsService,在 SecurityConfiguration 中自动连接ApplicationUserDetailsS ervice。 例子:

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

//This should work. If not Found it will give error. Might be the case  where it is injecting Other UserDetailsService.
@Autowired
private ApplicationUserDetailsService 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();
}

}

问题不在于注入 bean。 鉴于您看到的是预期的 bean 注入,原因可能是未使用该服务。

您需要检查您使用的身份验证提供程序。 对于默认提供程序,仅当您的身份验证提供程序基于用户名和密码时才使用该服务。

例如,参见 Spring 文档:

https://docs.spring.io/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/UserDetailsService.ZFC35FDC70D5FC69D23EZ8C

以下文章介绍了如何自定义用户详细信息。

https://docs.spring.io/spring-security/site/docs/5.2.x/reference/html/oauth2.html#oauth2login-advanced-oauth2-user-service

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM