在 CORS 期间 Spring-Boot RestController 失败

Posted

技术标签:

【中文标题】在 CORS 期间 Spring-Boot RestController 失败【英文标题】:Spring-Boot RestController fails during CORS 【发布时间】:2016-07-05 02:50:09 【问题描述】:

我正在尝试编写 CORS REST 服务。我的意思是一种 REST 服务,我可以从托管在 Web 服务器上的网站调用该服务,该网站的端口与 REST 服务器不同。

我正在使用 whatwg-fetch(Fetch API 客户端的 polyfill)和 REST 服务的 spring-boot。

package se.beta.note.rest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import se.selenwall.note.domain.Note;
import se.selenwall.note.domain.repository.NoteRepository;

import java.util.List;

@CrossOrigin(origins = "http://localhost:8001")
@RestController
public class NoteController 
    @Autowired
    private NoteRepository repository;

    @RequestMapping("/note")
    public List<Note> getNotes() 
        List<Note> notes = repository.findAll();
        System.out.println(notes);
        return notes;
    

    @RequestMapping(value = "/note", method = RequestMethod.POST)
    public void saveNote(@RequestBody @Validated Note note) 
        repository.save(note);
    

上面的代码可以很好地处理 GET 请求,但是 POST 失败。 Access-Control-Allow-Origin 未在对客户端的响应中设置。但是,它是在预检期间为OPTIONS 方法设置的。我无法控制 OPTIONS 和 POST 的发送方式,我只是使用 whatwg-fetch 并执行 POST,然后中间件自己执行 OPTIONS 和 POST。但主要问题是为什么我的 RestController 没有在 POST 请求中以 Access-Control-Allow-Origin 响应?

(我根本没有使用任何授权,POST请求的返回码是403 Forbidden。)

更新!正如我所怀疑的那样,403 Forbidden 与 CORS 无关,而是与 CSRF 相关。 POST 请求中缺少 CSRF 令牌。这是我现在面临的另一个问题:D 应该在 POST 请求中发送的 CSRF 令牌作为 OPTIONS 请求的响应中的标头发送到客户端。当使用 whatwg-fetch 时,我无法访问它们,因为 whatwg-fetch 处理的是自动预检和 POST。 有什么想法吗?

【问题讨论】:

来源真的是localhost 还需要添加支持跨域访问的HTTP Verbs(GET,POST...), 【参考方案1】:

您需要指导 Spring 如何处理 CORS 请求。要么使用 servlet 过滤器,要么使用 Spring 的 @CrossOrigin 注释,或者 CorsRegistry。本指南非常方便您使用https://spring.io/guides/gs/rest-service-cors/

【讨论】:

"或者使用Spring的@CrossOrigin注解"也许你应该仔细阅读这个问题。 看来我错过了...感谢您的关注。【参考方案2】:

删除NoteController.class中的@CrossOrigin注解

创建SimpleCORSFilter添加此代码

@Component
public class SimpleCORSFilter 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, PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Expose-Headers", "Location");
        chain.doFilter(req, res);
    

    public void init(FilterConfig filterConfig) 

    public void destroy() 


【讨论】:

“删除@CrossOrigin 注释” 为什么? 不需要使用@CrossOrigin 注释,因为此代码为 ServletRequest 请求和响应添加 CrossOrigin 标头 越野运动自带1.3...版本***.com/questions/31724994/spring-data-rest-and-cors 所以你假设 OP 不使用 Spring Boot 1.3+? 这里明确表示“CORS 支持将在即将发布的 Spring Boot 1.3 版本中提供,并且已经在 1.3.0.BUILD-SNAPSHOT 版本中提供。”和链接spring.io/blog/2015/06/08/cors-support-in-spring-framework

以上是关于在 CORS 期间 Spring-Boot RestController 失败的主要内容,如果未能解决你的问题,请参考以下文章

Angularjs + Spring-boot + nginx的CORS问题

带有 spring-boot 和 angularjs 的 CORS 不起作用

如何在 spring-boot 应用程序启动期间创建许多 kafka 主题?

在spring-boot启动期间tomcat数据源不检查有效连接?

通过 Firebase 函数触发器在没有 req/res 对象的情况下调用 cors(req,res,() => )

预检浏览器请求期间的 CORS 问题 [重复]