簡體   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