首页 > 解决方案 > Spring Boot RESTful 应用程序响应中的重复标头

问题描述

我已经多次看到这个问题,但似乎没有什么与我们的应用程序设置完全一致,所以我问它。

build.gradle(使用 gradle 7.1.1)

    plugins {
        id 'org.springframework.boot' version '2.5.3'
        id 'io.spring.dependency-management' version '1.0.11.RELEASE'
        id 'java'
        id 'war'
        id 'groovy'
        id 'idea'
    }
    group = 'com.dcblox'
    version = '0.0.2-SNAPSHOT'
    sourceCompatibility = 1.8
    repositories {
        mavenCentral()
        maven { url "https://dl.bintray.com/epam/reportportal" }
        maven { url "https://m2proxy.atlassian.com/repository/public" }
    }
    configurations {
        providedRuntime
    }
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-actuator'
        implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
        implementation 'org.springframework.boot:spring-boot-starter-security'
        implementation 'org.springframework.boot:spring-boot-starter-web'
        implementation 'org.springframework.boot:spring-boot-configuration-processor'
        developmentOnly 'org.springframework.boot:spring-boot-devtools'
        providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        testImplementation 'org.springframework.security:spring-security-test'
        implementation 'org.springframework:spring-test'
        testImplementation 'cglib:cglib-nodep:3.3.0'
        testImplementation 'org.objenesis:objenesis:3.2'
        implementation 'org.jetbrains:annotations:21.0.1'
        testImplementation 'org.codehaus.groovy:groovy-all:3.0.8'
        testImplementation 'org.spockframework:spock-core:2.0-groovy-3.0'
        testImplementation 'junit:junit:4.13.2'
    }
    compileJava {
        options.annotationProcessorPath = configurations.annotationProcessor
    }
    war {
        enabled = true
    }
    allprojects {
        gradle.projectsEvaluated {
            tasks.withType(JavaCompile) {
                options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
            }
        }
    }

WebConfig.java

@Configuration
@ComponentScan("com.acme.services.authenticate.interceptor")
public class WebConfig implements WebMvcConfigurer  {

    @Value("${APIURL}")
    private String APIURL;

    @Value("${environment}")
    String environment;

    private static final String SWAGGER_API_VERSION = "1.0";
    private static final String title = "REST API";
    private static final String description = "RESTful API";

    @Autowired
    AuthenticateInterceptor authenticateInterceptor;

    List<String> excludeURLs = new ArrayList<>();

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        excludeURLs.add("/webjars/**");
        excludeURLs.add("/authenticate/secondfactor");
        excludeURLs.add("/authenticate/requestSecondFactor");
        excludeURLs.add("/authenticate/login");
        excludeURLs.add("/user/newuserreset");
        excludeURLs.add("/user/admin/**");
        excludeURLs.add("/storage/admin");
        excludeURLs.add("/datacenter/**");
        excludeURLs.add("/storage/admin/**");
        excludeURLs.add("/user/passwordurl");
        excludeURLs.add("/user/forgotpassword");
        excludeURLs.add("/payment/");
        excludeURLs.add("/organization/admin");
        excludeURLs.add("/attachment/admin/**");
        excludeURLs.add("/documents/**");
        excludeURLs.add("/sign/**");
        excludeURLs.add("/organization/organizations/**");

        if(!environment.contains("prod")){
            excludeURLs.add("/authenticate/login/test");
        }

        registry.addInterceptor(authenticateInterceptor).excludePathPatterns(excludeURLs);
    }

    @Bean
    CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        filter.setForceEncoding(true);
        return filter;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

WebSecurityConfig.java

package com.acme.services.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
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.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;

import java.util.stream.Stream;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${app.allowedOrigins}")
    private String[] allowedOrigins;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(authorizeRequests ->
                    authorizeRequests.anyRequest().authenticated()
                )
                .cors()
                .configurationSource(corsConfigSource())
                .and()
                .csrf().disable();
    }

    private CorsConfigurationSource corsConfigSource() {
        final CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.addAllowedHeader(CorsConfiguration.ALL);
        corsConfig.addAllowedMethod(CorsConfiguration.ALL);
        corsConfig.setAllowCredentials(true);
        corsConfig.setMaxAge(1800L);
        Stream.of(allowedOrigins).forEach(
                origin -> corsConfig.addAllowedOriginPattern(origin)
        );
        return request -> corsConfig;
    }
}

应用程序.yml

app:
  name: middleware
  allowedOrigins: "http://127.0.0.1:8080,http://127.0.0.1:3000,http://10.1.143.100:8080,https://www.acme.com"
  environment: development
server:
  servlet:
    session:
      cookie:
        path: /

笔记:

  1. 我们不在控制器或控制器方法中使用@CrossOrigin 注释。
  2. 没有过滤器或实现过滤器类的@Components

此屏幕截图显示了响应标头响应头

我可能会遗漏一些东西来帮助找出问题的根源,如果是这样,请告诉我,我会发布它。

我知道某些东西必须加载两次,但对于我的生活,我无法弄清楚是什么。

任何帮助表示赞赏

标签: javaspringspring-bootspring-security

解决方案


推荐阅读