Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用

Posted

技术标签:

【中文标题】Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用【英文标题】:Spring Security Multiple HTTPSecurity with Different User Details Services Not Working in Spring Boot 【发布时间】:2020-01-01 08:11:37 【问题描述】:

我有两种类型的用户:应用程序用户和最终用户,我为这些用户设置了单独的表格。现在,我想对这两个表应用安全性。

我为应用程序用户提供了 UserDetailsS​​ervice 的自定义实现:

@Component("applicationUserDetailsService")
public class ApplicationUserDetailsService implements UserDetailsService 

而且,我为最终用户提供了 UserDetailsS​​ervice 的另一个自定义实现:

@Component("endUserDetailsService")
public class EndUserDetailsService implements UserDetailsService 

现在,在下面的代码 sn-p 中,我为这两种类型的用户注册了两个端点。我已经为应用程序和最终用户分别注入了 UserDetailsS​​ervice 的实现并通过 @Overide configure(AuthenticationManagerBuilder auth) 方法注册。

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration 

// Injected via Constructor Injection
private final EndUserDetailsService endUserDetailsService;

private final ApplicationUserDetailsService applicationUserDetailsService;

@Configuration
@Order(1)
public class ApplicationUserSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter 

    @Override
    public void configure(WebSecurity web) throws Exception 
        web.ignoring()
            .antMatchers(HttpMethod.OPTIONS, "/**")
            .antMatchers("/swagger-ui/index.html")
            .antMatchers("/test/**");
    

    @Override
    public void configure(HttpSecurity http) throws Exception 
        // @formatter:off
        http
            .csrf()
            .disable()
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling()
            .authenticationEntryPoint(problemSupport)
            .accessDeniedHandler(problemSupport)
            .and()
            .headers()
            .frameOptions()
            .disable()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .antMatcher("/api/customer/**")
            .authorizeRequests()
            .antMatchers("/api/customer/authenticate").permitAll()
            .antMatchers("/api/customer/**")
            .authenticated()
            .and()
            .apply(securityConfigurerAdapter());
        // @formatter:on
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(endUserDetailsService);
    


//no @Order defaults to last
@Configuration
public class EndUserSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter 

    @Override
    public void configure(WebSecurity web) throws Exception 
        web.ignoring()
            .antMatchers(HttpMethod.OPTIONS, "/**")
            .antMatchers("/swagger-ui/index.html")
            .antMatchers("/test/**");
    

    @Override
    public void configure(HttpSecurity http) throws Exception 
        // @formatter:off
        http
            .csrf()
            .disable()
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling()
            .authenticationEntryPoint(problemSupport)
            .accessDeniedHandler(problemSupport)
            .and()
            .headers()
            .frameOptions()
            .disable()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/**").authenticated()                               
            .and()
            .apply(securityConfigurerAdapter());
        // @formatter:on
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(applicationUserDetailsService);
    


private JWTConfigurer securityConfigurerAdapter() 
    return new JWTConfigurer(tokenProvider);


而且,我正在尝试像这样对用户进行身份验证:

//Injected via Constructor Injection
private final AuthenticationManagerBuilder authenticationManagerBuilder;

UsernamePasswordAuthenticationToken authenticationToken =
        new UsernamePasswordAuthenticationToken(loginVM.getUsername(), loginVM.getPassword());
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);

当上面的代码sn-p被执行时,我得到了空指针异常,因为authenticationManagerBuilder.getObject()返回空值。当我使用 @Component("userDetailsService") 实现 UserDetailService 并且没有在安全配置中设置 UserDetailService 时使用 @ 987654329@,它工作正常,但这样我无法从多个表中实现身份验证。

我想要实现的目标: 简而言之,我希望 Spring Security 从两个表中对用户进行身份验证。

【问题讨论】:

这正是我想要实现的目标:***.com/questions/52783807/… 但找不到任何方法 【参考方案1】:

requestMatchers() 是您需要的调用,因为它允许您通过 URL 隔离适配器:

@Order(1)
@EnableWebSecurity
class EndUserConfig extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            .requestMatchers()
                .antMatchers("/api/customer/**")
                .and()
            .authorizeRequests()
                .antMatchers("/**").hasRole("CUSTOMER")
                .and()
            .apply(yourJointConfigurations());
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(endUserDetailsService);
    
 

关于直接调用AuthenticationManager,如果您可以依靠现有的过滤器链为您完成工作,那将是理想的选择。例如,由于您是无状态的,HTTP Basic 可能更适合您,您可以将其应用于两种配置,而不是尝试使用专用的 /authenticate 端点。

【讨论】:

感谢您拯救了我的一天。

以上是关于Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

具有Spring Security的多个用户

Spring security 自定义用户详细信息@Id 问题

基于 Java Spring Security 的关注微信公众号即登录的设计与实现 ya

spring security - 针对不同 CURL 模式的多重身份验证

Spring Security 基于用户的权限? (不基于角色)

Spring Security-获取当前登录用户的详细信息