Spring CrossOrigin问题:没有Access-Control-Allow-Origin Header存在于请求的资源上,返回401作为HTTP响应

时间:2017-04-05 10:20:12

标签: spring spring-mvc spring-boot spring-security spring-data

我有一个API,它带有两个头ACCESS_TOKEN和TIME_OF_CALL以及输入参数,如下所述。

@RequestMapping(value = "/pay/capture", method = RequestMethod.GET)
@ResponseBody
@CrossOrigin(allowedHeaders = "ACCESS_TOKEN,TIME_OF_CALL", origins = "*")
public ResponseEntity<?> fetchRazorPayDetails(@RequestParam("id") Long id) 
{/***logics here*/}

从本地主机点击此API返回401说

XMLHttpRequest cannot load http://soandsoURL , response to preflight doesn't pass access control. check No Access-Control-Allow-Origin Header is present on the requested resource. origin 'http://localhost:1234' is therefore not allowed access. The response had HTTP status code 401

即使我已经明确注释了

  

@CrossOrigin(allowedHeaders =&#34; ACCESS_TOKEN,TIME_OF_CALL&#34 ;, originins =&#34; *&#34;)

接受所有来源和两个提到的标题。我错过了什么吗?  或者值为allowHeaders不能以逗号分隔?有关此问题的任何帮助  将不胜感激。

3 个答案:

答案 0 :(得分:1)

您可以添加自定义过滤器:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with, authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

答案 1 :(得分:0)

由于问题是选项(未经授权的401是错误),PFA截图。enter image description here

这只是因为我用@CrossOrigin声明/添加选项。早些时候它是`

@RequestMapping(value = "/pay/capture", method = RequestMethod.GET)
@ResponseBody
@CrossOrigin(allowedHeaders = "ACCESS_TOKEN,TIME_OF_CALL", origins = "*")
public ResponseEntity<?> fetchRazorPayDetails(@RequestParam("id") Long id) 
{/***logics here*/}`

我从@CrossOrigin中删除了可选参数,并将其保存为

    @RequestMapping(value = "/pay/capture", method = RequestMethod.GET)
    @ResponseBody
    @CrossOrigin
    public ResponseEntity<?> fetchRazorPayDetails(@RequestParam("id") Long id) 
    {/***logics here*/}

并且有效。

答案 2 :(得分:-1)

在自定义过滤器类中执行以下操作:

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = this.getAsHttpRequest(req);
    HttpServletResponse httpResponse=this.getAsHttpResponse(res);
    httpResponse.setHeader("Access-Control-Allow-Origin", "*");
    httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
    httpResponse.setHeader("Access-Control-Max-Age", "3600");
    httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with, authorization, ACCESS_TOKEN, TIME_OF_CALL");

    chain.doFilter(req, res);

}

private HttpServletResponse getAsHttpResponse(ServletResponse response)
{
    if (!(response instanceof HttpServletResponse)) {
        throw new RuntimeException("Expecting an HTTP request");
    }

    return (HttpServletResponse) response;
}

private HttpServletRequest getAsHttpRequest(ServletRequest request)
{
    if (!(request instanceof HttpServletRequest)) {
        throw new RuntimeException("Expecting an HTTP request");
    }

    return (HttpServletRequest) request;
}

并且在WebSecurity类中这样做。它会起作用

//To allow Pre-flight [OPTIONS] request from browser 
@Override
public void configure(WebSecurity web) throws Exception {
       web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}