You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security同时配置JWT与Basic认证的代码修改咨询

问题

我希望在Spring Security中同时使用两种不同的认证方式,具体需求如下:

  • /auth/** 和 /public/** 路径:允许所有用户访问,无需认证;
  • /api/** 路径:需通过JWT认证才能访问;
  • /orders/** 路径:需通过Basic认证才能访问。

以下是我的配置文件代码:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Configuration
    @Order(2)
    @AllArgsConstructor
    public static class JwtWebSecurityConfig extends WebSecurityConfigurerAdapter {

        private final UserService userService;
        private final JwtRequestFilter jwtRequestFilter;
        private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
        private final PasswordEncoder passwordEncoder;

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http
                .cors()
                    .and()
                .csrf().disable()
                .authorizeRequests()
                    .antMatchers("/auth/**", "/public/**").permitAll()
                    .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .exceptionHandling()
                    .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                    .and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            http
                .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        }

        @Autowired
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth
                .userDetailsService(userService)
                .passwordEncoder(passwordEncoder.bCryptPasswordEncoder());
        }

        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    }

    @Configuration
    @AllArgsConstructor
    @Order(1)
    public static class BasicAuth extends WebSecurityConfigurerAdapter {

        private final PasswordEncoder passwordEncoder;
        private final CustomBasicAuthenticationEntryPoint customBasicAuthenticationEntryPoint;

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth
                .inMemoryAuthentication()
                    .withUser("admin")
                        .password(passwordEncoder.bCryptPasswordEncoder().encode("user12345!"))
                        .roles("ADMIN");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http
                .authorizeRequests()
                    .antMatchers("/auth/**").permitAll()
                    .antMatchers("/public/**").permitAll()
                    .antMatchers("/orders/**").hasRole("ADMIN")
                    .and()
                .httpBasic();
        }
    }
}

请问上述代码中哪些部分需要修改以满足需求?


需要修改的部分

1. 明确配置类的路径处理范围,避免互相干扰

当前两个配置类的路径规则存在重叠,会导致请求被错误的认证逻辑拦截。需要通过requestMatchers()指定每个配置类负责的路径,实现隔离:

  • 修改JwtWebSecurityConfig的configure(HttpSecurity http):
    添加requestMatchers()限制仅处理/api/**、/auth/**、/public/**路径,同时排除/orders/**:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors()
                .and()
            .csrf().disable()
            .requestMatchers()
                .antMatchers("/api/**", "/auth/**", "/public/**")
                .and()
            .authorizeRequests()
                .antMatchers("/auth/**", "/public/**").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }
    
  • 修改BasicAuth的configure(HttpSecurity http):
    添加requestMatchers()限制仅处理/orders/**、/auth/**、/public/**路径,同时排除/api/**,并配置自定义认证入口点:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .requestMatchers()
                .antMatchers("/orders/**", "/auth/**", "/public/**")
                .and()
            .authorizeRequests()
                .antMatchers("/auth/**", "/public/**").permitAll()
                .antMatchers("/orders/**").hasRole("ADMIN")
                .and()
            .httpBasic()
                .authenticationEntryPoint(customBasicAuthenticationEntryPoint);
    }
    

2. 修复密码编码器的重复调用问题

假设PasswordEncoder的Bean已经是BCryptPasswordEncoder类型,无需重复调用bCryptPasswordEncoder()方法:

  • JwtWebSecurityConfig中的认证配置修改:

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userService)
            .passwordEncoder(passwordEncoder);
    }
    
  • BasicAuth中的密码编码修改:

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("admin")
                    .password(passwordEncoder.encode("user12345!"))
                    .roles("ADMIN");
    }
    

3. 确保自定义Basic认证入口点生效

BasicAuth类中注入了CustomBasicAuthenticationEntryPoint,但原代码未在配置中使用,需要在httpBasic()后添加该配置,保证认证失败时触发自定义错误处理(已包含在上面的BasicAuth配置修改中)。


内容的提问来源于stack exchange,提问作者Oğuzhan Erçelik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 07:05:17