执行POST请求时的Springboot端点403选项

时间:2018-03-24 23:54:01

标签: spring angular spring-boot

我正在使用Spring运行一个服务,我的Angular前端在尝试发出POST请求时使用请求方法获取403:OPTIONS。

Spring服务和Angular应用程序都在我的机器上本地运行。我尝试使用Chrome插件切换CORS,但这似乎无法解决问题。

我对该服务的所有GET请求似乎都正常。我可以在Postman中做POST请求,所以我不确定为什么角度应用程序无法提出请求,但Postman可以。

**** **** EDIT

响应标题

Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
Content-Length: 20
Date: Sat, 31 Mar 2018 19:15:01 GMT

请求标题

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: localhost:9901
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36

3 个答案:

答案 0 :(得分:3)

CORS请求由您的前端发出,以查看您支持的方法(HTTP Verbs)是什么。这通常是货币操作所必需的,例如POSTPUT,用于修改数据。

因此,您的前端将首先进行此调用,并且您的后端需要使用允许的方法进行响应,您还可以限制特定的URI,然后在成功验证后,进行目标调用。

这是完全正常的,角度在内部执行,以便在不知道服务器是否允许的情况下不会发出不必要的数据请求。

以下是Spring中的设置方式。

    //Change/Customize as necessary
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("<your origin>");
        corsConfiguration.setAllowedMethods(Arrays.asList(
                HttpMethod.GET.name(),
                HttpMethod.HEAD.name(),
                HttpMethod.POST.name(),
                HttpMethod.PUT.name(),
                HttpMethod.DELETE.name()));
        corsConfiguration.setMaxAge(1800L);
        source.registerCorsConfiguration("/**", corsConfiguration); // you restrict your path here
        return source;
    }

如果您还在后端使用任何自定义response headers,那么您还需要在CORS配置中允许这样做。 作为一个例子

    corsConfiguration.addAllowedHeader("*");
    corsConfiguration.addExposedHeader("header1");
    corsConfiguration.addExposedHeader("header2");

答案 1 :(得分:1)

如果我们谈论的是SpringBoot,大概是最新版本,或者至少是最新版本,那么我们可以在控制器类中的@CrossOrigin注释旁边使用@RestController注释。从春季版本开始可用。 4.2

例如:

@RestController
@CrossOrigin
@RequestMapping("/api")
public class MyObjectsController {
    private final MyObjectsService service;

    @Autowired
    public MyApiController(final MyObjectsService service) {
        this.service = service;
    }

    @GetMapping("/version")
    public Version getVersion() {
        return service.getVersion();
    }

    @PostMapping("/objects")
    public ObjectResource createObject(final @RequestBody @Valid ObjectData data) {
        return service.createObject(data);
    }

    @GetMapping("/objects/{id}")
    public ObjectResource getObject(final @PathVariable String id) {
        return service.getObjectById(id);
    }
}

好处:

  • 带注释的控制器的行为比任何一种自写过滤器都更好(更聪明)
  • 与整个项目的固定CORS配置相比,它还更灵活,因为您可以控制API的哪些部分应支持CORS标头,以及哪些部分仅可用于服务器之间的通信
  • 仅控制器支持的方法将在对OPTIONS请求的响应中声明并允许
  • CORS标头仅出现在对CORS请求的响应中(即分析了Referer标头的存在)

另请参阅:

答案 2 :(得分:0)

要解决Angular(前端)加Spring Boot(后端)项目中的所有CORS问题,请添加以下Spring组件:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ConfigCtrl implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        final HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
        response.setHeader("Access-Control-Max-Age", "3600");
        if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }
    @Override
        public void destroy() {
    }
    @Override
        public void init(FilterConfig config) throws ServletException {
    }
}

初学者的PS:班级的名称及其在Spring应用程序中的位置无关紧要。
Credit to Ajitesh Kumar.