我应该在 OPTIONS 请求之后的实际请求中发送任何 Access-Control-Allow-Origin header 到 non-allowed 来源吗?

Should I send any Access-Control-Allow-Origin header to non-allowed origins in the actual request following the OPTIONS request?

我对它的工作原理有一个大概的了解。如果请求的“来源”header 有效(允许),我 return 相同的“来源”值

但我不知道:

  1. 对于 OPTIONS 请求之后的实际请求,我是否需要包含与我 return 向客户端发送的预检请求完全相同的 Access-Control-Allow-Origin header?当实际请求中存在“ORIGIN”header 时,服务器代码是否只需要执行此操作? (在下面的代码中,我没有检查请求是 OPTIONS/preflight 请求还是实际请求,我假设相同的代码可以应用于两者而不会造成伤害)。

(更多细节,因为“当请求的凭证模式为'include'时,响应中'Access-Control-Allow-Origin' header的值不能是通配符'*',”所以我需要将请求中的 ORIGIN 值放回响应中。

  1. 如果ORIGIN不被允许,我应该return怎么办?

    根本不包括 Access-Control-Allow-Origin header?
    或 setHeader("Access-Control-Allow-Origin", ""), 或 setHeader("Access-Control-Allow-Origin", "null")?

public class CORSResponseFilter implements ContainerResponseFilter {

@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
    MultivaluedMap<String, Object> headers = responseContext.getHeaders();

    String origin = requestContext.getHeaderString("Origin"); 


String origin = requestContext.getHeaderString("Origin");

    URL originUrl = null;
    try {
        if (StringUtils.hasText(origin)) {
            originUrl = new URL(origin);
            
            Pattern hostAllowedPattern = Pattern.compile("(.+\.)*mydomain\.com", Pattern.CASE_INSENSITIVE);

            if (hostAllowedPattern.matcher(originUrl.getHost()).matches()) {
                headers.add("Access-Control-Allow-Origin", origin);
            } else {
                headers.add("Access-Control-Allow-Origin", "");
            }
            headers.add("Vary", "Origin");
        }

        headers.add("Access-Control-Allow-Credentials", "true");
        headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        headers.add("Access-Control-Allow-Headers",

For the actual request following the OPTIONS request, do I need to include the exact same Access-Control-Allow-Origin header that I returned to the client for the preflight request?

是——也就是说,如果您发回的是实际的原始值而不是“*”通配符,并且该原始值是导致 OPTIONS 请求成功的原因。因为如果您发回的 non-wildcard 原始值与 OPTIONS 成功返回的原始值不同,这将导致浏览器阻止客户端代码访问响应(因为实际来源不匹配) .

Should the server code only need to do this when there is an "ORIGIN" header present in the actual request?

是的,因为当浏览器中的前端 JavaScript 代码 运行 使用 XHR 或 Fetch API 或某个 JavaScript 库中的 Ajax 方法时要发出 cross-origin 请求,浏览器总是会在请求中添加 Origin header。并且 Access-Control-Allow-Origin 仅供浏览器使用。

因此,将 Access-Control-Allow-Origin 发回给未在请求中发送 Origin 的 non-browser 工具是没有意义的——在这种情况下,这只是浪费字节发出去。

当然有人可以使用 curl 或任何 non-browser 工具向服务器发送请求,并手动向请求添加 Origin header。但这没关系——在这种情况下,他们将获得的响应与您发送到浏览器的响应相同。所以这实际上对测试很有帮助。

What should I return if the ORIGIN is not allowed?
not including the Access-Control-Allow-Origin header at all?

是的。对于这些情况,根本不要发回 Access-Control-Allow-Origin 响应 header。这就是缺少 header 的语义:如果服务器未发送 Access-Control-Allow-Origin 响应 header,则意味着服务器未选择允许来自前端代码的 cross-origin 请求运行 个浏览器,因此默认 same-origin 政策适用。

也就是说,通过不发送 Access-Control-Allow-Origin 响应 header,服务器告诉浏览器:“请像往常一样使用默认的 same-origin 策略并禁止访问发送此请求的所有前端 JavaScript 代码的此响应。”

or setHeader("Access-Control-Allow-Origin", ""),

不,永远不需要像那样发回空值。这并不意味着什么特别的。

or setHeader("Access-Control-Allow-Origin", "null")?

绝对不要那样做。在许多情况下,浏览器会发送 Origin header 值 null ,除非您有意允许所有带有 Origin: null 的请求访问来自服务器的响应,不要那样做。

有关详细信息,请参阅 当浏览器必须在内部将 origin 设置为将被序列化为 null 的值时When does Firefox set the Origin header to null in POST requests?

的部分答案