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

问题描述 投票:0回答:5

我正在使用 Spring 运行一个服务,当我的 Angular 前端尝试发出 POST 请求时,会收到带有请求方法:选项的 403 错误。

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

我对服务的所有 GET 请求似乎都工作正常。我可以在 Postman 中执行 POST 请求,所以我不确定为什么 Angular 应用程序无法发出请求,但 Postman 可以。

****编辑****

响应标头

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
spring angular spring-boot
5个回答
14
投票

CORS 请求由您的前端发出,以查看您的支持者允许哪些方法 (

HTTP Verbs
)。这通常是货币操作所必需的,例如用于修改数据的
POST
PUT

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

这是完全正常的,Angular 在内部执行此操作,以免在不知道服务器是否允许的情况下发出不必要的数据请求。

以下是您在

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");

8
投票

要修复 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 应用程序中的位置并不重要。
感谢 Ajitesh Kumar。


5
投票

如果我们谈论的是 SpringBoot,大概是最新的或至少是最近的版本,那么我们可以简单地在控制器类中的

@CrossOrigin
注释旁边使用
@RestController
注释。从 Spring 版本开始可用。 4.2

例如:

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

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

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

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

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

好处:

  • 带注释的控制器比任何类型的自写过滤器表现得更好(也更智能)
  • 它比整个项目的固定 CORS 配置更灵活,因为您可以控制 API 的哪些部分应支持 CORS 标头以及哪些部分应仅用于服务器到服务器通信
  • 只有控制器支持的方法才会在对 OPTIONS 请求的响应中声明和允许
  • CORS 标头仅出现在对 CORS 请求的响应中(即分析
    Referer
    标头的存在)
  • 等等

另请参阅:


0
投票

就我而言,问题在于标头中接受的模式,它是

cn.app.filters.cors-filter.allowed-path-pattern=/appname/**

更正为

cn.app.filters.cors-filter.allowed-path-pattern=/**

希望这有帮助!


-1
投票

永远记住,当我们在 Spring Boot 中配置令牌基础身份验证时,对于 cors,我们必须在 configure( HttpSecurity http){} 方法中进行配置* 否则,预检请求会收到 403

@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAt(tokenAuthFilter(), 
BasicAuthenticationFilter.class);
//this is configuratio of cors
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    config.setAllowCredentials(false);
   http.csrf().disable()
   //and this way we can setup configuration
   .cors().configurationSource((option)->{

               return config;
           })
  .and()
  .authorizeHttpRequests()
           
  .antMatchers("/api/user/create","/api/user/authenticate","/v3/api- 
  docs/**","/v3/swagger**/**", "/v3/swagger-ui.html", "/v3/swagger- 
  ui/**")
           .permitAll()
           .anyRequest()
           .authenticated();
}
© www.soinside.com 2019 - 2024. All rights reserved.