我有一个RESTful Web服务,其中包含许多不同的资源(端点),当从Postman调用这些资源时,它们都能很好地工作。但是,仅其中一些可通过浏览器工作,而其余的则失败。我无法在失败的URL和未失败的URL中发现任何模式。
我正在直接从Chrome控制台调用资源。
例如,这是浏览器无法使用的资源,但可以从Postman- / api / hello / 使用。
fetch("https://myapp.herokuapp.com/api/hello/", {method: "GET", headers: {"authToken" : "7c577770c0b7f1b2ba0f7dbb10ae247978a9997cf8aec3bbab0ac7de409e0b4c"}})
.then(res => res.json())
.then(console.log)
例如,这是Postman和Chrome均可使用的资源。
fetch("https://myapp.herokuapp.com/api/user/all/", {method: "GET", headers: {"authToken" : "7c577770c0b7f1b2ba0f7dbb10ae247978a9997cf8aec3bbab0ac7de409e0b4c"}})
.then(res => res.json())
.then(console.log)
对于失败的资源,Chrome记录了以下错误。
Access to fetch at 'https://myapp.herokuapp.com/api/hello/' from origin 'http://admin.myapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
我观察到,如果我尝试获取服务上实际上不存在的资源,则会出现完全相同的消息,例如,调用 / api / blabla / 会导致完全相同的错误
我在Spring中的CORS配置如下。
@Component
public class SimpleCORSFilter implements Filter {
private static final String DEFAULT_ORIGIN = "https://admin.myapp.com";
private static final Set<String> allowedOrigins = new HashSet<>();
static {
allowedOrigins.add(DEFAULT_ORIGIN);
allowedOrigins.add("http://admin.myapp.com");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
final String origin = request.getHeader("Origin");
if (origin != null && allowedOrigins.contains(origin)) {
// set origin to our specific domain to disallow request from other sites
response.setHeader("Access-Control-Allow-Origin", origin);
} else {
// set origin to our default allowed
response.setHeader("Access-Control-Allow-Origin", DEFAULT_ORIGIN);
}
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", String.format("%s, %s", "Content-Type", HEADER_AUTH_TOKEN));
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
我可以看到,对于来自Postman的任何呼叫,以及来自Chrome的未报告错误的呼叫,响应头均已完美设置。但是,在确实报告错误的Chrome调用中,Access-Control-Allowed-Methods仅包含GET。
TL; DR-我不知道为什么从浏览器进行的CORS调用仅对某些资源失败,而对于其他资源却无法正常工作。
答案 0 :(得分:0)
Spring会自动处理CORS preflight请求。
但是您并没有真正使用Spring's CORS functionality,因此您应该通过返回HTTP 200 OK来处理OPTIONS请求。
类似这样的东西:
if ("OPTIONS".equals(req.getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
(尽管我不认为这是造成您问题的根本原因)