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

将Spring Security XML配置迁移至Spring Boot Java配置咨询

Spring Security Java配置实现

以下是将你提供的Spring Security XML配置转换为Spring Boot Java配置的实现,完全对应原配置的功能:

基于WebSecurityConfigurerAdapter的实现(适配Spring Security 5.7以下版本)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    // 注册自定义LoginFilter,对应XML中的<beans:bean id="LoginFilter" class="com.codemaster.LoginFilter"/>
    @Bean
    public LoginFilter loginFilter() {
        return new LoginFilter();
    }

    // 第一个HttpSecurity配置,对应XML中pattern="/dashboard*"的<http>块,优先级更高
    @Configuration
    @Order(1)
    public static class DashboardSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    // 匹配/dashboard*路径
                    .antMatcher("/dashboard*")
                    // 权限控制:/dashboard*需要ROLE_NORMAL_USER角色
                    .authorizeRequests()
                        .antMatchers("/dashboard*").access("hasRole('ROLE_NORMAL_USER')")
                        .and()
                    // 表单登录配置
                    .formLogin()
                        .loginPage("/logout")
                        .defaultSuccessUrl("/dashboard")
                        .failureUrl("/loginerrorpage")
                        .and()
                    // 会话并发控制:最多12个会话,过期跳转/logout
                    .sessionManagement()
                        .maximumSessions(12)
                        .expiredUrl("/logout")
                        .and()
                        .and()
                    // 添加自定义过滤器到LOGIN_PAGE_FILTER之后
                    .addFilterAfter(loginFilter(), UsernamePasswordAuthenticationFilter.class)
                    // 登出配置
                    .logout()
                        .invalidateHttpSession(true)
                        .logoutUrl("/j_spring_security_logout")
                        .logoutSuccessUrl("/logout")
                        .and()
                    // 禁用CSRF
                    .csrf().disable();
        }
    }

    // 第二个HttpSecurity配置,对应XML中第二个<http>块,优先级较低
    @Configuration
    @Order(2)
    public static class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    // 权限控制:/entrance需要ROLE_NORMAL_USER角色
                    .authorizeRequests()
                        .antMatchers("/entrance").access("hasRole('ROLE_NORMAL_USER')")
                        .and()
                    // 表单登录配置
                    .formLogin()
                        .loginPage("/login")
                        .defaultSuccessUrl("/entrance")
                        .failureUrl("/loginerrorpage")
                        .and()
                    // 会话并发控制
                    .sessionManagement()
                        .maximumSessions(12)
                        .expiredUrl("/logout")
                        .and()
                        .and()
                    // 登出配置
                    .logout()
                        .invalidateHttpSession(true)
                        .logoutUrl("/j_spring_security_logout")
                        .logoutSuccessUrl("/logout")
                        .and()
                    // 禁用CSRF
                    .csrf().disable();
        }
    }

    // 内存用户认证配置,对应XML中的<authentication-manager>
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("user1")
                .password(passwordEncoder().encode("password1"))
                .roles("NORMAL_USER")
                .and()
                .withUser("user2")
                .password(passwordEncoder().encode("password2"))
                .roles("NORMAL_USER");
    }

    // 密码编码器:适配原XML的明文密码(生产环境请替换为安全编码器)
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}

基于SecurityFilterChain的实现(Spring Security 5.7+官方推荐)

如果你的项目使用Spring Security 5.7.0及以上版本,建议使用组件式配置替代WebSecurityConfigurerAdapter:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public LoginFilter loginFilter() {
        return new LoginFilter();
    }

    @Bean
    @Order(1)
    public SecurityFilterChain dashboardSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .antMatcher("/dashboard*")
                .authorizeRequests(auth -> auth
                        .antMatchers("/dashboard*").access("hasRole('ROLE_NORMAL_USER')")
                )
                .formLogin(form -> form
                        .loginPage("/logout")
                        .defaultSuccessUrl("/dashboard")
                        .failureUrl("/loginerrorpage")
                )
                .sessionManagement(session -> session
                        .maximumSessions(12)
                        .expiredUrl("/logout")
                )
                .addFilterAfter(loginFilter(), UsernamePasswordAuthenticationFilter.class)
                .logout(logout -> logout
                        .invalidateHttpSession(true)
                        .logoutUrl("/j_spring_security_logout")
                        .logoutSuccessUrl("/logout")
                )
                .csrf(csrf -> csrf.disable());

        return http.build();
    }

    @Bean
    @Order(2)
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(auth -> auth
                        .antMatchers("/entrance").access("hasRole('ROLE_NORMAL_USER')")
                )
                .formLogin(form -> form
                        .loginPage("/login")
                        .defaultSuccessUrl("/entrance")
                        .failureUrl("/loginerrorpage")
                )
                .sessionManagement(session -> session
                        .maximumSessions(12)
                        .expiredUrl("/logout")
                )
                .logout(logout -> logout
                        .invalidateHttpSession(true)
                        .logoutUrl("/j_spring_security_logout")
                        .logoutSuccessUrl("/logout")
                )
                .csrf(csrf -> csrf.disable());

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user1 = User.withUsername("user1")
                .password(passwordEncoder().encode("password1"))
                .roles("NORMAL_USER")
                .build();

        UserDetails user2 = User.withUsername("user2")
                .password(passwordEncoder().encode("password2"))
                .roles("NORMAL_USER")
                .build();

        return new InMemoryUserDetailsManager(user1, user2);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}

关键说明

  1. 多HttpSecurity配置:通过@Order指定优先级,数字越小优先级越高,完全对应原XML的两个独立<http>块。
  2. 自定义过滤器:使用addFilterAfter将LoginFilter添加到指定过滤器之后,对应XML的<custom-filter>配置。
  3. 密码编码器:NoOpPasswordEncoder仅用于适配原XML的明文密码,生产环境必须替换为BCryptPasswordEncoder等安全编码器。
  4. 会话控制:maximumSessions(12)和expiredUrl("/logout")完全对应原XML的会话并发配置。

内容的提问来源于stack exchange,提问作者Kunal Bhangale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:30:55