我的 Spring boot 应用程序中的 PatternParseException

问题描述 投票:0回答:1

我正在从 Spring boot 2 应用程序迁移到 Spring boot 3, 我在 Spring Security 中做了所有更改,并且应用程序启动正常。当我调用端点时,我收到 PatternParseException,我认为这是因为我的 Spring Security 配置。

您可以在下面找到我的 Spring 安全配置和 Web 配置。

org.springframework.web.util.pattern.PatternParseException: No more pattern data allowed after {*...} or ** pattern element
        at org.springframework.web.util.pattern.InternalPathPatternParser.peekDoubleWildcard(InternalPathPatternParser.java:250) ~[spring-web-6.0.11.jar!/:6.0.11]
        at org.springframework.web.util.pattern.InternalPathPatternParser.parse(InternalPathPatternParser.java:113) ~[spring-web-6.0.11.jar!/:6.0.11]
        at org.springframework.web.util.pattern.PathPatternParser.parse(PathPatternParser.java:129) ~[spring-web-6.0.11.jar!/:6.0.11]
        at org.springframework.web.servlet.handler.PathPatternMatchableHandlerMapping.lambda$match$0(PathPatternMatchableHandlerMapping.java:64) ~[spring-webmvc-6.0.11.jar!/:6.0.11]
        at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[na:na]

安全配置

package com.omb.restcore.security;

import com.omb.core.security.utils.JasyptEncryptorDecryptor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    private static final Logger LOG = Logger.getLogger(SecurityConfig.class.getName());
    private static final String HEALTHCHECK_URL = "/**/healthCheck";
    private static final String[] ALLOW_LIST = {
            HEALTHCHECK_URL, "/**/v3/api-docs", "/**/swagger-resources/**",
            "/**/swagger-ui.html", "/**/webjars/**", "/**/csrf", "/", "/**/css/**"
    };
    @Value("${enableHttpAuthentication:true}")
    private boolean enableHttpAuthentication;
    @Value("${enableLoginEncryption}")
    private boolean enableLoginEncryption;
    @Value("${allowAnonymousAccessToSwaggerDoc}")
    private boolean allowAnonymousAccessToSwaggerDoc;
    @Autowired
    private Environment environment;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        if (enableHttpAuthentication) {
            // Accept only BASIC authenticated requests except for the given ressources, which are accessible without
            // authentication
            if (allowAnonymousAccessToSwaggerDoc) {
                http.csrf(csrf -> csrf.disable())
                        .authorizeHttpRequests(auth -> auth.requestMatchers(ALLOW_LIST).permitAll()
                                .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                                .anyRequest().authenticated())
                        .httpBasic(Customizer.withDefaults());
            } else {
                http.csrf(csrf -> csrf.disable())
                        .authorizeHttpRequests(auth -> auth.requestMatchers(HEALTHCHECK_URL).permitAll()
                                .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                                .anyRequest().authenticated())
                        .httpBasic(Customizer.withDefaults());
            }
            LOG.info("BASIC HTTP authentication enabled");
        } else {
            // Disable authentication on API usage
            http.csrf(csrf -> csrf.disable())
                    .authorizeHttpRequests(auth -> auth.anyRequest().anonymous());
            LOG.info("BASIC HTTP authentication disabled");
        }

        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("*"));
        configuration.setAllowedMethods(List.of("*"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Requestor-Type"));
        configuration.setExposedHeaders(List.of("X-Get-Header"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuth = auth.inMemoryAuthentication();

        for (PropertySource<?> propertySource : ((AbstractEnvironment) environment).getPropertySources()) {
            if (propertySource instanceof MapPropertySource) {
                Map<String, Object> properties = ((MapPropertySource) propertySource).getSource();
                java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("user\\.(.*)\\.password");

                for (String k : properties.keySet()) {
                    java.util.regex.Matcher matcher = pattern.matcher(k);

                    if (matcher.find()) {
                        String user = matcher.group(1);
                        String pwd = properties.get(k).toString();

                        if (enableLoginEncryption) {
                            user = JasyptEncryptorDecryptor.decrypt(user);
                        }
                        pwd = JasyptEncryptorDecryptor.decrypt(pwd);

                        if (!StringUtils.isEmpty(pwd)) {
                            LOG.finest("Configured HTTP BASIC access rights for user " + user);
                            inMemoryAuth.withUser(user).password("{noop}" + pwd).roles("USER");
                        } else {
                            LOG.finest("Disabled HTTP BASIC access rights for user " + user);
                        }
                    }
                }
            }
        }

        LOG.info("BASIC HTTP configuration done.");
    }
}

网络配置

package com.omb.gateway.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOriginPatterns("*")
                        .allowedHeaders("Requestor-Type")
                        .exposedHeaders("X-Get-Header")
                        .allowCredentials(true);
            }
        };
    }
}
java spring-boot spring-security
1个回答
0
投票

我通过更改这些行来解决我的问题

错误的路径模式定义:

private static final String HEALTHCHECK_URL = "/**/healthCheck";
private static final String[] ALLOW_LIST = {
            HEALTHCHECK_URL, "/**/v3/api-docs", "/**/swagger-resources/**",
            "/**/swagger-ui.html", "/**/webjars/**", "/**/csrf", "/", "/**/css/**"
    };

良好的路径模式定义:

private static final String HEALTHCHECK_URL = "/healthCheck/**";
private static final String[] ALLOW_LIST = {
            HEALTHCHECK_URL, "/v3/api-docs/**", "/swagger-resources/**",
            "/swagger-ui.html/**", "/webjars/**", "/csrf/**", "/**", "/css/**"
    };
© www.soinside.com 2019 - 2024. All rights reserved.