Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用 [英] Spring Security Multiple HTTPSecurity with Different User Details Services Not Working in Spring Boot

查看:35
本文介绍了Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two types of users: Application User and End User and I have separate tables for these. Now, I want to apply security on these two tables.

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

I provided custom implementation of UserDetailsService for Application users:

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

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

And, I provided another second custom implementation of UserDetailsService for End users:

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

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

Now, in the following code snippet, I have registered two endpoints for both type of users. I have injected both implementation of UserDetailsService and registered by @Overide configure(AuthenticationManagerBuilder auth) method for both application and end user separately.

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

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

And, I'm trying to authenticate the user like this:

//Injected via Constructor Injection
private final AuthenticationManagerBuilder authenticationManagerBuilder;

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

当执行上述代码片段时,我得到空指针异常,因为 authenticationManagerBuilder.getObject() 返回 NULL.当我使用 UserDetailService@Component("userDetailsS​​ervice") 实现 UserDetailService 而没有设置 UserDetailService 时em> 在像 auth.userDetailsS​​ervice("...") 这样的安全配置中,它工作正常,但这样我无法从多个表中实现身份验证.

When the above code snippet is executed, I get the Null Pointer Exception because authenticationManagerBuilder.getObject() returns NULL. And when I use just when implementation of UserDetailService with @Component("userDetailsService") and not set UserDetailService in security config like auth.userDetailsService("..."), it works fine but by that way I can't achieve authentication from multiple tables.

我想要实现的目标:简单来说,我希望 spring security 从两个表中对用户进行身份验证.

What I want to Achieve: In simple words, I want spring security to authenticate user from two tables.

推荐答案

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

requestMatchers() is the call that you need as it allows you to isolate adapters by 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 端点.

Regarding calling the AuthenticationManager directly, it would be ideal if you could rely on the existing filter chain to do the work for you. For example, since you are stateless, HTTP Basic might be a better fit for you, which you could apply to both configurations, instead of trying to have a dedicated /authenticate endpoint.

这篇关于Spring Security 具有不同用户详细信息的多个 HTTPSecurity 服务在 Spring Boot 中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆