使用 Spring Framework 为 OPTIONS 请求启用 CORS

2022-01-15 00:00:00 cors spring ajax java spring-mvc

每次我对我的服务进行 PUT Ajax 调用时,它都会返回以下错误:

Every time I make a PUT Ajax call to my service, it return the following error:

XMLHttpRequest 无法加载 http://localhost:8080/users/edit.对预检请求的响应未通过访问控制检查:请求的资源上不存在Access-Control-Allow-Origin"标头.Origin 'http://localhost:63342' 因此不允许访问.响应的 HTTP 状态代码为 403.

XMLHttpRequest cannot load http://localhost:8080/users/edit. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. The response had HTTP status code 403.

经过 2 天的调查,我已经尝试在我的代码上尝试下一个解决方案.

After 2 days of investigation, I've reached to try the next solution on my code.

这是我加载必要的类并运行应用程序的主类:

This is the main class where I load the necessary classes and run the application:

@SpringBootApplication
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer{

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DispatcherServletInitializer.class, OptionsController.class,Application.class);
    }
}

DispatcherServilet 初始化程序,我在其中启用了 dispatchOptionsRequest:

The DispatcherServilet initializer, where I enable the dispatchOptionsRequest:

public abstract class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setInitParameter("dispatchOptionsRequest", "true");
        super.customizeRegistration(registration);
    }
}

用于处理所有 OPTIONS 请求的 控制器:

A controller for handle all OPTIONS request:

@Controller
public class OptionsController {

    @RequestMapping(method = RequestMethod.OPTIONS)
    public HttpServletResponse handle(HttpServletResponse theHttpServletResponse) throws IOException {
        theHttpServletResponse.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with");
        theHttpServletResponse.addHeader("Access-Control-Max-Age", "60"); 
        theHttpServletResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        theHttpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
        return theHttpServletResponse;
    }

}

我做错了什么配置?

推荐答案

最后,DispatcheServlet 自定义初始化程序是真正解决我的问题的类.OPTIONS 请求失败,因为我实现了 optionsController,这是错误的.

Finally, the DispatcheServlet customize initializer was the class that really solved my problem. The OPTIONS request was failing because of the optionsController I had implemented, it was wrong.

所以我删除了那个 optionsController,并且仅仅通过在我的 Rest Controller 中为 OPTIONS 请求添加 handle 方法,问题就解决了:

So I removed that optionsController, and just by adding the handle method in my Rest Controller for the OPTIONS request, the problem was solved:

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/users")
public class Users {

    @RequestMapping(
            value = "/edit",
            method = RequestMethod.PUT)
    public ResponseEntity<?> create(@RequestBody User user){
         ....
         ....
    }

    @RequestMapping(
            value = "/**",
            method = RequestMethod.OPTIONS
    )
    public ResponseEntity handle() {
        return new ResponseEntity(HttpStatus.OK);
    }
}

相关文章