Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring引导数据Rest+;未正确启用选项/删除的CORS_Java_Spring_Rest_Spring Mvc_Spring Data Rest - Fatal编程技术网

Java Spring引导数据Rest+;未正确启用选项/删除的CORS

Java Spring引导数据Rest+;未正确启用选项/删除的CORS,java,spring,rest,spring-mvc,spring-data-rest,Java,Spring,Rest,Spring Mvc,Spring Data Rest,我有一个非常简单的例子,我无法开始工作 我有我的域,它为我的数据库和存储库建模 public interface MyTestRepository extends CrudRepository<MyTest, Integer> { } 我搜索了一下,找到了这个 所以我补充说 @Bean public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlB

我有一个非常简单的例子,我无法开始工作

我有我的域,它为我的数据库和存储库建模

public interface MyTestRepository extends CrudRepository<MyTest, Integer> {
}
我搜索了一下,找到了这个

所以我补充说

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}
我还发现了这条线

并尝试了以下代码,但没有成功

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("HEAD");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    source.registerCorsConfiguration("/**", config);
    // return new CorsFilter(source);
    final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}
我在测试中添加了一个catch-all,它应该允许所有CORS-wise都通过,但是我仍然得到了No‘Access-Control-allow-Origin’,即使我有“*”

在这一点上,我不知道为什么飞行前的请求没有通过访问控制检查,我遗漏了什么

curl发出delete命令没有问题

编辑:

最终找到了确切的解决方案。我不确定我所拥有的和这种方法之间的区别,但这似乎是可行的

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Note this is a very simple CORS filter that is wide open.
 * This would need to be locked down.
 * Source: https://stackoverflow.com/questions/39565438/no-access-control-allow-origin-error-with-spring-restful-hosted-in-pivotal-web
 */
@Component
public class CORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {}

    public void destroy() {}

}

这就是我使用的permit all CORS servlet过滤器:

public class PermissiveCORSFilter implements Filter {

    private static final Logger LOGGER = LoggerFactory.getLogger(PermissiveCORSFilter.class);
    private static final Pattern PATTERN = Pattern.compile("^[a-zA-Z0-9 ,-_]*$");

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        String origin;
        String credentialFlag;
        if (request.getHeader("Origin") == null) {
            origin = "*";
            credentialFlag = "false";
         } else {
            origin = request.getHeader("Origin");
            credentialFlag = "true";
         }

        // need to do origin.toString() to avoid findbugs error about response splitting        
        response.addHeader("Access-Control-Allow-Origin", origin.toString());
        response.setHeader("Access-Control-Allow-Credentials", credentialFlag);
        if ("OPTIONS".equals(request.getMethod())) {
            LOGGER.info("Received OPTIONS request from origin:" + request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS,PUT,DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            String headers = StringUtils.trimToEmpty(request.getHeader("Access-Control-Request-Headers"));
            if (!PATTERN.matcher(headers).matches()) {
                throw new ServletException("Invalid value provided for 'Access-Control-Request-Headers' header");
            }
            response.setHeader("Access-Control-Allow-Headers", headers); // allow any headers
        }
        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {
        // Do nothing
    }

    @Override
    public void destroy() {
        // Do nothing
    }

以下配置适用于基于SpringDataREST的应用程序。需要注意的重要一点是,在安全过滤器链启动之前,过滤器已注册以执行

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
  @Override
  public void configure(HttpSecurity http) throws Exception
  {
    http.addFilterBefore(corsFilter(), ChannelProcessingFilter.class);
  }

  @Bean
  protected Filter corsFilter()
  {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("HEAD");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    config.addExposedHeader("Location");

    source.registerCorsConfiguration("/**", config);

    return new CorsFilter(source);
  }
}

使用弹簧靴2.2.6

我必须添加一个过滤器以允许选项工作。没有它,我得到了403。“Origin”请求头触发了在Postman中测试的403-I,在没有发送该头的情况下,选项在没有过滤器的情况下工作

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
@Component
            
        public class CORSFilter implements Filter {
                
                public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
                    HttpServletResponse response = (HttpServletResponse) res;
                    response.setHeader("Access-Control-Allow-Origin", "*");
                    response.setHeader("Access-Control-Allow-Methods", "OPTIONS");  // "POST, GET, PUT, OPTIONS, DELETE"
                    response.setHeader("Access-Control-Max-Age", "3600");
                    response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
                    chain.doFilter(req, res);
                }
        
            public void init(FilterConfig filterConfig) {}
        
            public void destroy() {}
        
        }
连同

@Configuration
public class ConfigCORS implements WebMvcConfigurer {
@Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/**")  
                .allowedOrigins("*")  allowedOrigins("http://localhost:3000")
                .allowedMethods("POST", "PUT", "GET",  "DELETE", "OPTIONS") 
                .allowedHeaders("Content-Type", "Origin")
                .exposedHeaders("X-Total-Count", "Location", "Access-Control-Allow-Origin")  
                .allowCredentials(false)
                .maxAge(6000);
    }
}

我似乎也有同样的问题。CrossOrigin配置可以很好地使用GET/PUT/POST,但是当我请求Spring PostMapping方法的选项时,响应会忽略Access Control Allow Methods标头:

@CrossOrigin
public class ArticleController {

@DeleteMapping("/{uuid}")
public void delete(@PathVariable String uuid) throws ArticleNotFoundException {
    articleService.delete(uuid);
}
如果我curl for DELETE,我会得到一个包含访问控制允许方法的HTTP 200:

$ curl -v -H "Access-Control-Request-Method: DELETE" -H "Origin: http://localhost:4200" -X OPTIONS http://localhost:8080/article/someuuid
< HTTP/1.1 200
< Access-Control-Allow-Origin: http://localhost:4200
< Access-Control-Allow-Methods: PUT,POST,GET,DELETE,OPTIONS
< Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
这导致:

$ curl -v -H "Access-Control-Request-Method: OPTIONS" -H "Origin: http://localhost:4200" -X OPTIONS http://localhost:8080/article/someuuid
< HTTP/1.1 200
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: OPTIONS
< Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH

谢谢,但是基于我的OP中的那个bug,它对我不起作用,因为我使用的是SpringDataRESTOK,这很有趣。。我们使用的是spring mvc+spring数据,当从我们的angular web客户端调用该过滤器时,该过滤器似乎工作正常。您是否使用自动生成的存储库?e、 g.Repository(){}?我用@CrossOrigin(origins=“*”)标记要测试的类似乎没有这个问题。好的,我将得到纠正。我试图使用你的代码,但似乎不起作用。我最终找到了这个,将代码复制并粘贴到一个类中,它成功了。这和你的想法是一样的。我会将你的问题标记为答案,但我会在我的问题中添加一个编辑,这是适合我的完整代码(请随意添加到你的答案中)。我仍然不明白3个不同的CORS过滤器之间的区别。谢谢:)是的,它看起来很相似,可能与需要显式允许删除的“访问控制允许方法”有关。谢谢,但这似乎也不起作用。我将其复制并粘贴到我的Spring应用程序中,禁用了添加导入的所有其他@Configuration类,但仍然得到相同的错误。您正在使用Springs引导数据Rest吗?如果是这样,您是否使用自动生成REST端点的Repository类?当使用straight Spring Boot MVC/REST而不使用Spring Boot starter安全性时,我必须使用上面的CORSFIlter来允许预引导选项工作。如果没有过滤器,当我使用Postman发送带有Origin头的选项请求时,我得到了一个403禁止(如果我不使用Origin,选项可以正常工作)。我需要“公共类CORSFilter implements Filter”和“公共类CORSconfiguration implements WebMVCConfiguer”来获得正确工作的选项
$ curl -v -H "Access-Control-Request-Method: OPTIONS" -H "Origin: http://localhost:4200" -X OPTIONS http://localhost:8080/article/someuuid
< HTTP/1.1 403
@RequestMapping(
        value = "/**",
        method = RequestMethod.OPTIONS
)
public ResponseEntity handle() {
    return new ResponseEntity(HttpStatus.OK);
}
$ curl -v -H "Access-Control-Request-Method: OPTIONS" -H "Origin: http://localhost:4200" -X OPTIONS http://localhost:8080/article/someuuid
< HTTP/1.1 200
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: OPTIONS
< Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
@RequestMapping("/article")
@CrossOrigin(origins="http://localhost:4200",
    methods = {RequestMethod.PUT, RequestMethod.POST, RequestMethod.GET, RequestMethod.DELETE, RequestMethod.OPTIONS}
    )
public class ArticleController {

@RequestMapping(
        value = "/{uuid}",
        method = { RequestMethod.DELETE })
public void delete(@PathVariable String uuid) throws ArticleNotFoundException {
    articleService.delete(uuid);
}

@RequestMapping(method = { RequestMethod.OPTIONS})
public ResponseEntity handle() {
    return new ResponseEntity(HttpStatus.OK);
}