从Spring Boot 2.6.6升级到Spring Boot 3.1.2的Spring Security升级

3

我正在将一个Spring Boot应用程序从Spring Boot 2.6.6迁移到3.1.2,其中大部分http security中的方法要么已弃用,要么已删除。

我在很多地方进行了搜索,但是无法将此特定配置转换为Spring Boot 3.1.X配置。

以下是使用扩展WebSecurityConfigurerAdapter类编写的方法。 注意:preAuthFilter()、accessDeniedHandler()和forbiddenEntryPoint()是同一类中定义的方法。

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/**").exceptionHandling().authenticationEntryPoint(forbiddenEntryPoint())
            .and().authorizeRequests().antMatchers(
                "/**/index*",
                "/**/logout/",
                "/**/logoutApp",
                "/rest/getversion*",
                "/rest/dologin/*",
                "/rest/menu*",
                "/rest/getScript*",
                "/rest/**").permitAll().antMatchers("/rest/saveTodo*").hasRole("ADMIN")
            .antMatchers("/**").denyAll()
            .and()
            .addFilterAt(preAuthFilter(), AbstractPreAuthenticatedProcessingFilter.class)
            .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
            .and().csrf().disable()
            .headers().disable();
    }

@Override
    public void configure(WebSecurity web) {
        web
            .ignoring()
            .antMatchers("/**/*.png*","/**/*.js*","/**/*.jpg*","/**/*.svg*","/**/*.ico*",
                "/**/*.css*","/**/login*","/**/*.woff*","/**/*.ttf*","/**/*.eot*");
    }


我尝试将上述代码改为下面的代码:
@Bean
public SecurityFilterChain springFilterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(req -> req.requestMatchers(
                new AntPathRequestMatcher(new AntPathRequestMatcher("/**"))))
                    .exceptionHandling(request -> request.authenticationEntryPoint(forbiddenEntryPoint()))
                    .authorizeHttpRequests(request -> request
                            .requestMatchers(
                                    new AntPathRequestMatcher("/**/index*"), 
                                    new AntPathRequestMatcher("/**/logout/"),
                                    new AntPathRequestMatcher("/**/logoutApp"), 
                                    new AntPathRequestMatcher("/rest/getversion*"),
                                    new AntPathRequestMatcher("/rest/dologin/*"),
                                    new AntPathRequestMatcher("/rest/menu*"),
                                    new AntPathRequestMatcher("/rest/getScript*"), 
                                    new AntPathRequestMatcher("/rest/**"),
                                    new AntPathRequestMatcher("/waveinventoryservice/**"))
                            .permitAll()
                            .requestMatchers(new AntPathRequestMatcher("/rest/saveTodo*")).hasRole("ADMIN")
                            .requestMatchers(new AntPathRequestMatcher("/**"))
                            .denyAll())
                    .addFilterAt(preAuthFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                    .exceptionHandling(handler -> handler.accessDeniedHandler(accessDeniedHandler()))
                    .csrf(CsrfConfigurer::disable).headers(HeadersConfigurer::disable).build();
}

@Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers(new AntPathRequestMatcher("/**/*.png*"),
                new AntPathRequestMatcher("/**/*.js*"),
                new AntPathRequestMatcher("/**/*.jpg*"),
                new AntPathRequestMatcher("/**/*.svg*"),
                new AntPathRequestMatcher("/**/*.ico*"),
                new AntPathRequestMatcher("/**/*.css*"),
                new AntPathRequestMatcher("/**/login*"),
                new AntPathRequestMatcher("/**/*.woff*"),
                new AntPathRequestMatcher("/**/*.ttf*"),
                new AntPathRequestMatcher("/**/*.eot*"));
    }

这段代码似乎不工作,因为在调用方法 SecurityContextHolder.getContext().getAuthentication() 时,控制器和过滤器中返回了 null,即使在一个 API 中设置了 URL "rest/dologin/{userId}"。
之前使用旧的配置是可以工作的,但现在不行了,请有人帮助我更改这个配置吗?

我添加了一个可以帮助你的答案,我认为。 - undefined
3个回答

0
我在Spring Boot 3中进行了安全配置,也许这可以帮到你。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    private final JwtFilter jwtFilter;
    private final JwtAuthenticationEntryPoint authenticationEntryPoint;
    private final JWTAccessDeniedHandler accessDeniedHandler;

    public SecurityConfig(JwtFilter jwtFilter, JwtAuthenticationEntryPoint authenticationEntryPoint, JWTAccessDeniedHandler accessDeniedHandler) {
        this.jwtFilter = jwtFilter;
        this.authenticationEntryPoint = authenticationEntryPoint;
        this.accessDeniedHandler = accessDeniedHandler;
    }

    @Bean
    public AuthenticationManager authenticationManager(final AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .headers().frameOptions().disable().and()
                .csrf().disable()
                .cors().and()
                .authorizeHttpRequests(auth -> {
                    auth.requestMatchers("/api/public", "/h2-console/**", "/api/auth/login", "/api/auth/signup", "/**").permitAll();
                    auth.requestMatchers("/api/v1/admin").hasAuthority("ADMIN");
                    auth.requestMatchers("/api/v1/area").hasAnyAuthority("ADMIN", "USER");
                    auth.anyRequest().authenticated();
                })
                .formLogin().disable()
                .httpBasic().disable()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler)
                .authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers
                ("/api/public", "/h2-console/**", "/api/auth/login", "/api/auth/signup", "/**");
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedMethods("*");
            }
        };
    }
}

嗨Enes,但可悲的是and()和disable()已被弃用,而auth.requestMatchers("anyApi")给我报错:该方法无法确定这些模式是否为Spring MVC模式。如果此端点是Spring MVC端点,请使用requestMatchers(MvcRequestMatcher);否则,请使用requestMatchers(AntPathRequestMatcher)。 - undefined

0
Spring Security已经更新了。不幸的是,WebSecurityConfigurerAdapter不再受支持。你可以在这里查看。这可能对你有所帮助:
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;    
import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

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

        AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
        http.addFilter(new CustomFilter(authenticationManager));

        http.authorizeHttpRequests((authz) -> authz
                        .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                        .requestMatchers("/rest/saveTodo*").hasRole("ADMIN")
                        .requestMatchers("/**").denyAll()
                        .requestMatchers(
                                "/**/index*",
                                "/**/logout/",
                                "/**/logoutApp",
                                "/rest/getversion*",
                                "/rest/dologin/*",
                                "/rest/menu*",
                                "/rest/getScript*",
                                "/rest/**").permitAll()
                        .anyRequest().permitAll())
                .formLogin(withDefaults()).exceptionHandling((exceptionHandling) ->
                        exceptionHandling.authenticationEntryPoint(forbiddenEntryPoint()))
                .exceptionHandling((exceptionHandling) ->
                        exceptionHandling.accessDeniedHandler(accessDeniedHandler())) // Use the AccessDeniedHandler bean here
                .and()             
                .csrf().disable()
                .headers().disable();     


}

1
嗨 @azizkale, 谢谢你的回复,我知道 spring-security 的 WebSecurityConfigurerAdapter 已经被弃用了,我需要移除这个类。如果你仔细看的话,我已经在实际问题中展示的代码中进行了更改。但是似乎还是不起作用。我会检查一下并告诉你是否有效! - undefined
这对我的案件有所帮助。你可以查看它:https://www.youtube.com/watch?v=mkdVgx0ylpU - undefined

0
根据您提供的信息,在迁移到3.1.2版本之前,一切都很顺利,并且SecurityContextHolder.getContext().getAuthentication()没有返回null。问题出在最新的配置上。
另外,根据2.6.6的旧配置,3.1.2的配置应该是这样的:
  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
      http.csrf(AbstractHttpConfigurer::disable);
      http.headers(AbstractHttpConfigurer::disable);
      http.exceptionHandling(handlingConfigurer -> {
              handlingConfigurer.accessDeniedPage(accessDeniedHandler());
              handlingConfigurer.authenticationEntryPoint(forbiddenEntryPoint());
      });
      http.addFilterAt(preAuthFilter(), AbstractPreAuthenticatedProcessingFilter.class);
      http.authorizeHttpRequests(request -> {
         request.requestMatchers("/**/index*",
             "/**/logout/",
             "/**/logoutApp",
             "/rest/getversion*",
             "/rest/dologin/*",
             "/rest/menu*",
             "/rest/getScript*",
             "/rest/**").permitAll();
         request.requestMatchers("/rest/saveTodo*").hasRole("ADMIN");
         request.requestMatchers("/**").denyAll();
          });
      return http.build();
    }

  @Bean
  public WebSecurityCustomizer webSecurityCustomizer() {
    return (web) -> web.ignoring().requestMatchers("/**/*.png*","/**/*.js*","/**/*.jpg*","/**/*.svg*","/**/*.ico*",
            "/**/*.css*","/**/login*","/**/*.woff*","/**/*.ttf*","/**/*.eot*");
  }

嗨 @Anderi Lisa,谢谢你的回复,我会尝试并告诉你。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接