Spring Security CORS 过滤器不起作用

8
我正在使用Spring Security和OAuth2(版本:4.0.4.RELEASE)以及Spring(版本:4.3.1.RELEASE)。我在Angular中开发前端,并使用grunt connect:dev(http://127.0.0.1:9000)。当我尝试通过本地主机地址登录时,一切正常,但从其他地方登录时出现错误:
“XMLHttpRequest无法加载http://localhost:8084/oauth/token?client_id=MY_CLIENT_ID。对预检请求的响应未能通过访问控制检查:所请求的资源上没有'Access-Control-Allow-Origin'头。因此,源'http://127.0.0.1:9000'不允许访问。响应的HTTP状态码为401。”
我已经在WebMvcConfigurerAdapter中配置了映射(覆盖了public void addCorsMappings(CorsRegistry registry)),如下所示,但仍然不能用于http://127.0.0.1:9000
    registry.addMapping("/**")
            .allowedOrigins("http://127.0.0.1:9000")
            .allowedMethods("POST", "OPTIONS", "GET", "DELETE", "PUT")
            .allowedHeaders("X-Requested-With,Origin,Content-Type,Accept,Authorization")
            .allowCredentials(true).maxAge(3600);

基于以下配置:https://spring.io/guides/gs/rest-service-cors/

请指引我解决这个问题的正确方向。


如果我理解正确,您正在尝试从不同的IP地址127.0.0.1访问(您不再在本地主机上)。但是,您只允许从本地主机(127.0.0.1)访问。 - Periklis Douvitsas
可能是重复的问题:Spring CORS No 'Access-Control-Allow-Origin' header is present - Oleg Kurbatov
Periklis - 是的,我正在尝试从不同的IP地址访问。我的许可证只允许从http://localhost:8084/ 访问。 - Matt
Oleg Kurbatov - 谢谢,我知道这个链接,但是所有的东西都是根据文档来的。我按照文档中的步骤做了一切,但它仍然不能正常工作。在我的配置中,我没有使用web.xml文件。 - Matt
如何对过滤器进行排序?有什么想法吗? - Matt
4个回答

21

希望你早就找到了答案,但如果没有(或者其他人像我一样搜索到了这个问题):

问题在于Spring Security使用过滤器,这些过滤器通常比用户定义的过滤器、@CrossOrigin和类似的注释等具有优先级。

对我有效的方法是将CORS过滤器定义为具有最高优先级的bean,如此处建议的那样。

@Configuration
public class MyConfiguration {

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://127.0.0.1:9000");
        config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT"));
        config.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}

帮助我解决了这个问题。然而,FilterRegistrationBean是参数化的。 - amdg

2
抱歉回复时间有点长。我通过以下方式配置我的CORS过滤器解决了问题:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {

    private static final Logger LOGGER = LogManager.getLogger(CORSFilter.class.getName());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;
        final String origin = ((HttpServletRequest) req).getHeader("Origin");

        if (ofNullable(origin).isPresent() && origin.equals("http://127.0.0.1:9000")) {
            LOGGER.info("CORSFilter run");
            response.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:9000");
            response.addHeader("Access-Control-Allow-Credentials", "true");

            if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
                response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                response.addHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Authorization");
                response.setStatus(200);
            }
        }
        chain.doFilter(addNessesaryHeaders(request), response);
    }


    private MutableHttpServletRequest addNessesaryHeaders(final HttpServletRequest request) {
        final MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(request);
        mutableRequest.putHeader("Accept", "application/json");
        mutableRequest.putHeader("Authorization", "Basic" + " bXVzaWNzY2hvb2w6");
        return mutableRequest;
    }

    @Override
    public void destroy() {
    }
}

0
你可以尝试这样做。
@Configuration
public class CorsConfig {
   @Bean
   public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
          @Override
          public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedMethods(HttpMethod.OPTIONS.name(),
                            HttpMethod.PATCH.name(),
                            HttpMethod.PUT.name(),
                            HttpMethod.DELETE.name(),
                            HttpMethod.GET.name(),
                            HttpMethod.POST.name())
                    .maxAge(360);
            }
       };
   }
}

注意:Spring 版本应为 4.2 或更高版本


你可以尝试添加:.allowedHeaders("header1", "header2"),接受从客户端发送到服务器的头部变量。 - NguaCon
1
你的问题解决了吗?如果是的话,能否提供解决方案?因为我在我的应用程序中也遇到了同样的错误。 - sireesha j

0

以下方法适用于我。

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

  @Configuration
  @EnableWebMvc
  public class MvcConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");     
  }
}

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