• Spring Security 替换WebSecurityConfigurerAdapter (Deprecated)的方法


    在本文中,我将提供一个解决方案来配置Spring 安全性,而无需 WebSecurityConfigurerAdapter 类。从 Spring Security 5.7 开始,WebSecurityConfigurerAdapter类已被弃用,Spring 团队鼓励用户转向基于组件的安全配置。
     

    使用 WebSecurityConfigurerAdapter

    WebSecurityConfigurerAdapter类被弃用之前,我们正在编写这样的代码。我们创建了一个Spring Java配置类,它扩展了WebSecurityConfigurerAdapter类并覆盖了几个configure()方法:
    1. @Configuration
    2. @EnableWebSecurity
    3. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    4. @Override
    5. protected void configure(HttpSecurity http) throws Exception {
    6. // configure HTTP security...
    7. }
    8. @Override
    9. public void configure(WebSecurity web) throws Exception {
    10. // configure Web security...
    11. }
    12. }
    从春季安全 5.7.0-M2 开始。WebSecurityConfigurerAdapter类已被弃用,Spring 团队鼓励用户转向基于组件的安全配置。

    没有网络安全配置器适配器

    在使用基于组件的 Spring 安全配置的新方法中,您需要遵循以下非常简单的步骤:
    1. 删除 WebSecurityConfigurerAdapter 类(不要扩展WebSecurityConfigurerAdapter
    2. 删除网络安全配置器适配器类的所有重写方法
    3. 使用SecurityFilterChain 配置 HttpSecurity,使用WebSecurityCustomizer 配置 WebSecurity
    1. @Configuration
    2. @EnableWebSecurity
    3. public class SecurityConfiguration {
    4. @Bean
    5. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    6. // configure HTTP security...
    7. }
    8. @Bean
    9. public WebSecurityCustomizer webSecurityCustomizer() {
    10. // configure Web security...
    11. }
    12. }
    让我们看一个完整的示例供您参考。

    没有网络安全的 Spring 安全性配置器适配器示例

    考虑我们在下面使用WebSecurityConfigurerAdapter类进行 Spring 安全配置,稍后我们将看到如何将此安全配置迁移到基于组件的方法。
    package net.javaguides.springboot.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
    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.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    
    import net.javaguides.springboot.service.UserService;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    	@Autowired
    	private UserService userService;
    	
    	@Bean
        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    	
    	@Bean
        public DaoAuthenticationProvider authenticationProvider() {
            DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
            auth.setUserDetailsService(userService);
            auth.setPasswordEncoder(passwordEncoder());
            return auth;
        }
    	
    	@Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(authenticationProvider());
        }
    	
    	@Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http.authorizeRequests().antMatchers(
    				 "/registration**",
    	                "/js/**",
    	                "/css/**",
    	                "/img/**").permitAll()
    		.anyRequest().authenticated()
    		.and()
    		.formLogin()
    		.loginPage("/login")
    		.permitAll()
    		.and()
    		.logout()
    		.invalidateHttpSession(true)
    		.clearAuthentication(true)
    		.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
    		.logoutSuccessUrl("/login?logout")
    		.permitAll();
    	}
    
    }
    接下来,这是没有 WebSecurityConfigurerAdapter 的基于组件的替代方法:
    package net.javaguides.springboot.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.SecurityFilterChain;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    
    @Configuration
    @EnableWebSecurity
    public class SpringSecurity {
    
    //    @Autowired
    //    private UserDetailsService userDetailsService;
    
        @Bean
        public static PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        // configure SecurityFilterChain
        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .authorizeRequests()
                    .antMatchers("/register/**").permitAll()
                    .antMatchers("/index").permitAll()
                    .antMatchers("/users").hasRole("ADMIN")
                    .and()
                    .formLogin(
                            form -> form
                                    .loginPage("/login")
                                    .loginProcessingUrl("/login")
                                    .defaultSuccessUrl("/users")
                                    .permitAll()
                    ).logout(
                            logout -> logout
                                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                                    .permitAll()
    
                    );
            return http.build();
        }
    
    //    @Autowired
    //    public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
    //        builder.userDetailsService(userDetailsService)
    //                .passwordEncoder(passwordEncoder());
    //    }
    }

    在上面的例子中,我们遵循最佳实践,使用 Spring Security lambda DSL 和方法HttpSecurity#authorizeHttpRequests来定义我们的授权规则。如果你不熟悉lambda DSL,你可以在这篇博文中阅读它。

    重要:我们不再需要手动将UserDetailsServicePasswordEncoder设置为AuthenticationManager实例,它只需要存在于spring上下文中。一旦我们将UserDetailsServicePasswordEncoder配置为Spring bean,Spring Security就会自动设置为AuthenticationManager

    Spring Security JWT (JSON Web Token) without WebSecurityConfigurerAdapter

    考虑我们有以下的 spring 安全性和使用WebSecurityConfigurerAdapter类的 JWT 配置,稍后我们将看到如何将此安全配置迁移到基于组件的方法。
    package com.springboot.blog.config;
    
    import com.springboot.blog.security.CustomUserDetailsService;
    import com.springboot.blog.security.JwtAuthenticationEntryPoint;
    import com.springboot.blog.security.JwtAuthenticationFilter;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    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.config.http.SessionCreationPolicy;
    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.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private CustomUserDetailsService userDetailsService;
    
        @Autowired
        private JwtAuthenticationEntryPoint authenticationEntryPoint;
    
        @Bean
        public JwtAuthenticationFilter jwtAuthenticationFilter(){
            return  new JwtAuthenticationFilter();
        }
    
        @Bean
        PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .csrf().disable()
                    .exceptionHandling()
                    .authenticationEntryPoint(authenticationEntryPoint)
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .antMatchers(HttpMethod.GET, "/api/v1/**").permitAll()
                    .antMatchers("/api/v1/auth/**").permitAll()
                    .antMatchers("/v2/api-docs/**").permitAll()
                    .antMatchers("/swagger-ui/**").permitAll()
                    .antMatchers("/swagger-resources/**").permitAll()
                    .antMatchers("/swagger-ui.html").permitAll()
                    .antMatchers("/webjars/**").permitAll()
                    .anyRequest()
                    .authenticated();
            http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService)
                    .passwordEncoder(passwordEncoder());
        }
    
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        //    @Override
    //    @Bean
    //    protected UserDetailsService userDetailsService() {
    //        UserDetails ramesh = User.builder().username("ramesh").password(passwordEncoder()
    //                .encode("password")).roles("USER").build();
    //        UserDetails admin = User.builder().username("admin").password(passwordEncoder()
    //                .encode("admin")).roles("ADMIN").build();
    //        return new InMemoryUserDetailsManager(ramesh, admin);
    //    }
    }
    接下来,这是没有 WebSecurityConfigurerAdapter 的基于组件的替代方法:
    package com.springboot.blog.config;
    
    import com.springboot.blog.security.CustomUserDetailsService;
    import com.springboot.blog.security.JwtAuthenticationEntryPoint;
    import com.springboot.blog.security.JwtAuthenticationFilter;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    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.config.http.SessionCreationPolicy;
    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.bcrypt.BCryptPasswordEncoder;
    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
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig {
    
        @Autowired
        private CustomUserDetailsService userDetailsService;
    
        @Autowired
        private JwtAuthenticationEntryPoint authenticationEntryPoint;
    
        @Bean
        public JwtAuthenticationFilter jwtAuthenticationFilter(){
            return  new JwtAuthenticationFilter();
        }
    
        @Bean
        PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        protected SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
            http
                    .csrf().disable()
                    .exceptionHandling()
                    .authenticationEntryPoint(authenticationEntryPoint)
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests((authorize) -> authorize
                            .antMatchers(HttpMethod.GET, "/api/v1/**").permitAll()
                            .antMatchers("/api/v1/auth/**").permitAll()
                            .antMatchers("/v2/api-docs/**").permitAll()
                            .antMatchers("/swagger-ui/**").permitAll()
                            .antMatchers("/swagger-resources/**").permitAll()
                            .antMatchers("/swagger-ui.html").permitAll()
                            .antMatchers("/webjars/**").permitAll()
                            .anyRequest()
                            .authenticated()
                    );
            http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
            return http.build();
        }
    
    
    //    @Override
    //    protected void configure(HttpSecurity http) throws Exception {
    //        http
    //                .csrf().disable()
    //                .exceptionHandling()
    //                .authenticationEntryPoint(authenticationEntryPoint)
    //                .and()
    //                .sessionManagement()
    //                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    //                .and()
    //                .authorizeRequests()
    //                .antMatchers(HttpMethod.GET, "/api/v1/**").permitAll()
    //                .antMatchers("/api/v1/auth/**").permitAll()
    //                .antMatchers("/v2/api-docs/**").permitAll()
    //                .antMatchers("/swagger-ui/**").permitAll()
    //                .antMatchers("/swagger-resources/**").permitAll()
    //                .antMatchers("/swagger-ui.html").permitAll()
    //                .antMatchers("/webjars/**").permitAll()
    //                .anyRequest()
    //                .authenticated();
    //        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    //    }
    
        @Bean
        public AuthenticationManager authenticationManager(
                AuthenticationConfiguration authenticationConfiguration) throws Exception {
            return authenticationConfiguration.getAuthenticationManager();
        }
    
    //    @Override
    //    @Bean
    //    public AuthenticationManager authenticationManagerBean() throws Exception {
    //        return super.authenticationManagerBean();
    //    }
    
        //    @Override
    //    @Bean
    //    protected UserDetailsService userDetailsService() {
    //        UserDetails ramesh = User.builder().username("ramesh").password(passwordEncoder()
    //                .encode("password")).roles("USER").build();
    //        UserDetails admin = User.builder().username("admin").password(passwordEncoder()
    //                .encode("admin")).roles("ADMIN").build();
    //        return new InMemoryUserDetailsManager(ramesh, admin);
    //    }
    }

    没有网络安全配置器适配器的分步完整示例

    引用

  • 相关阅读:
    基于minikube快速搭建kubernetes单节点环境
    自定义NavigationBar--使用UIView进行绘制
    bitbucket.org 用法
    SpringBoot-Web开发-文件上传
    刷题笔记:二叉树的中序遍历(三种解法-递归,迭代,Morris)
    单细胞文献学习(part5)--Using Cell-to-Cell Variability— A New Era in Molecular Biology
    Java代理模式
    OTA升级常见错误码汇总-CSDN博客
    基于MATLAB的变换编码的设计与实现
    SpringBoot 拦截org.thymeleaf.exceptions.TemplateInputException异常
  • 原文地址:https://blog.csdn.net/allway2/article/details/127781632