Spring 4.2.0.RC2和Tomcat 8.0.23中的CORS问题

时间:2015-07-07 22:15:37

标签: java spring spring-mvc tomcat

在我使用Spring 4.1.x版本之前,我有自己的Cors Filter和Interceptor。我也使用Tomcat 8.0.8一切都很好。

由于我将相同的应用程序移动到Tomcat 8.0.23,CORS停止了工作。

因此,我在POM中将应用程序更新为以下版本的Spring依赖项:

org.springframework: 4.2.0.RC2
org.springframework.security: 4.0.1.RELEASE
org.springframework.security.oauth2: 2.0.7.RELEASE
org.springframework.ws.version: 2.2.0.RELEASE
spring.data.commons.core.version: 1.4.1.RELEASE

现在,我还更新了我的securityConfiguration.xml,以获得安全4.0.1.RELEASE的正确模式。

应用程序运行正常,除CORS外,所有更改都完美无缺。

所以我按照说明操作并添加到我的WebMvcConfigurerAdapter实现类中:

@Override
    public void addCorsMappings(CorsRegistry registry) {
        Properties prop = null;

        try {

            InputStream in = getClass().getResourceAsStream(
                    "/com/nando/config/cors.properties");
            prop = new Properties();
            prop.load(in);
            in.close();            
        } catch (IOException e) {
            prop = null;
        }

        if (prop != null) {
            String domains = prop.getProperty("allowed.origins");

            List<String> allowedOrigins = new ArrayList<String>(
                    Arrays.asList(domains.split(",")));

            if (allowedOrigins.size() > 0) {
                String[] arrayOrigins = null;
                arrayOrigins = new String[allowedOrigins.size()];
                arrayOrigins = allowedOrigins.toArray(arrayOrigins);
                registry.addMapping("/**")
                .allowedOrigins(arrayOrigins)
                .allowedMethods("PUT, POST, GET, OPTIONS, DELETE")
                .allowedHeaders("*")
                .exposedHeaders("Authorization", "Content-Type")
                .allowCredentials(false).maxAge(3600);
            }
        } else {
            registry.addMapping("/**")
            .allowedOrigins("*")
            .allowedMethods("PUT, POST, GET, OPTIONS, DELETE")
            .allowedHeaders("*")
            .exposedHeaders("Authorization", "Content-Type")
            .allowCredentials(false).maxAge(3600);
        }
    }

单独执行此操作并不能解决问题,尽管使用调试器到Tomcat我可以看到正确执行和添加。我有一个属性文件,以便我可以更改允许的域而无需重新编译应用程序,就像我之前在4.1.x Spring上使用自己的实现一样。

因为我将此应用程序作为OAuth2应用程序,所以我也实现了拦截器。

在我的WebMvcConfigurerAdapter实现之前我有一个拦截器,所以我试图将它添加到它:

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CORSInterceptor());
        super.addInterceptors(registry);
    }

加载我的CORSInterceptor实现如下:

package com.nando.api.filters;

import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * 
 * @author Nando
 *
 */
@Component
public class CORSInterceptor extends HandlerInterceptorAdapter {

    private Properties prop = new Properties();

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {

        InputStream in = getClass().getResourceAsStream("/com/nando/config/cors.properties");
        prop.load(in);
        in.close();

        String domains = prop.getProperty("allowed.origins");

        Set<String> allowedOrigins = new HashSet<String>(Arrays.asList(domains
                .split(",")));

        String originHeader = "";
        originHeader = request.getHeader("Origin");

        if (null != originHeader) {
            for (String s : allowedOrigins) {
                if (originHeader.contains(s)) {
                    if (!response.getHeaderNames().contains("Access-Control-Allow-Origin")) {
                        response.addHeader("Access-Control-Allow-Origin",
                                originHeader);
                    }
                    if (!response.getHeaderNames().contains("Access-Control-Allow-Methods")) {
                        response.addHeader("Access-Control-Allow-Methods",
                                "OPTIONS, GET, POST, PUT, DELETE, HEAD");
                    }
                    if (!response.getHeaderNames().contains("Access-Control-Allow-Credentials")) {
                        response.addHeader("Access-Control-Allow-Credentials", "true");
                    }
                    if (!response.getHeaderNames().contains("Access-Control-Allow-Headers")) {
                        response.addHeader("Access-Control-Allow-Headers",
                            "Authorization, Origin, Content-Type, x-Requested-with, Accept, Accept-Enconding, X-CSRF-Token");
                    }
if (!response.getHeaderNames().contains("Access-Control-Max-Age")) {
 response.addHeader("Access-Control-Max-Age", "1800");
                    }
                    return true;
                }
            }
        }
        return true;
    }
}

仍然无法发挥作用。

我不想将CORS过滤器添加到Tomcat,因为它不允许我在属性文件上设置域,强迫我在每次添加或删除域时编辑Tomcat实例配置。

看起来我有一个难题。

另外我认为通过遵循Spring 4.2关于设置CORS的指示会使事情变得容易,但事实并非如此。

有人可以帮忙吗?

谢谢,

卡洛斯。

1 个答案:

答案 0 :(得分:6)

如果您想使用Spring CORS支持,我认为您应该:

  • allowedMethods("PUT, POST, GET, OPTIONS, DELETE")更改为allowedMethods("PUT", "POST", "GET", "OPTIONS", "DELETE")(这是一个varargs参数)
  • 删除allowedHeaders("*"),它已经是默认值
  • 删除CORSInterceptor
  • 删除Tomcat CORS过滤器
  • 检查它是否在没有Spring Security的情况下工作
  • 根据Brian的建议,请向我们提供有关HTTP请求/响应的更多详细信息

作为替代方案,请注意Spring Framework 4.2 GA还提供了CorsFilter实现,可以与UrlBasedCorsConfigurationSource结合使用以提供全局CORS支持。

如果您使用的是Spring Boot(支持Filter bean),那么在@Configuration注释类中可能会出现类似情况:

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    config.addExposedHeader("Authorization");
    config.addExposedHeader("Content-Type");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}