了解跨源资源共享(CORS)

Adobe Experience Manager的跨源资源共享(CORS)使非AEM Web资产能够对AEM进行客户端调用(无论经过身份验证还是未经身份验证),以获取内容或直接与AEM交互。

本文档中概述的OSGI配置足以满足以下要求:

  1. AEM Publish上的单源资源共享
  2. 对AEM Author的CORS访问权限

如果AEM Publish上需要多源CORS访问,请参阅本文档

AdobeGranite跨源资源共享策略OSGi配置

CORS配置在AEM中作为OSGi配置工厂进行管理,每个策略都表示为工厂的一个实例。

  • http://<host>:<port>/system/console/configMgr > Adobe Granite Cross Origin Resource Sharing Policy

AdobeGranite跨源资源共享策略OSGi配置

Adobe Granite Cross-Origin Resource Sharing Policy (com.adobe.granite.cors.impl.CORSPolicyImpl)

策略选择

通过比较

  • 具有Origin请求标头的Allowed Origin
  • Allowed Paths,请求路径为。

将使用匹配这些值的第一个策略。 如果未找到任何请求,则会拒绝任何CORS请求。

如果根本未配置策略,则不会应答CORS请求,因为处理程序已禁用,从而有效地被拒绝 — 只要服务器的其他模块没有响应CORS。

策略属性

允许的源

  • "alloworigin" <origin> | *
  • origin参数的列表,这些参数指定可以访问资源的URI。 对于没有凭据的请求,服务器可以将*指定为通配符,从而允许任何源访问资源。 绝对不建议在生产中使用Allow-Origin: *,因为它允许所有外部(即攻击者)网站发出浏览器严格禁止不带CORS的请求。

允许的源(Regexp)

  • "alloworiginregexp" <regexp>
  • regexp正则表达式的列表,这些表达式指定可以访问资源的URI。 如果不仔细构建,则正则表达式可能会导致意外匹配,使得攻击者使用也会匹配策略的自定义域名。 ​通常建议使用alloworigin为每个特定的原始主机名设置单独的策略,即使这意味着重复配置其他策略属性也是如此。 不同的起源往往具有不同的生命周期和要求,从而有利于清晰的分离。

允许的路径

  • "allowedpaths" <regexp>
  • 指定策略适用的资源路径的regexp正则表达式的列表。

公开的标头

  • "exposedheaders" <header>
  • 标头参数列表,指示允许浏览器访问的响应标头。 对于CORS请求(非预检),如果不为空,这些值将复制到Access-Control-Expose-Headers响应标头。 随后,浏览器将能够访问列表中的值(标头名称);如果没有这些标头,浏览器将无法读取这些标头。

最大年龄

  • "maxage" <seconds>
  • 一个seconds参数,用于指示可以缓存预检请求结果的时长。

支持的标头

  • "supportedheaders" <header>
  • header参数的列表,指示在发出实际请求时可以使用哪些HTTP请求标头。

允许的方法

  • "supportedmethods"
  • 方法参数列表,指示在发出实际请求时可以使用哪些HTTP方法。

支持凭据

  • "supportscredentials" <boolean>
  • 一个boolean,用于指示对请求的响应是否可以向浏览器公开。 当用作对飞行前请求的响应的一部分时,这指示是否可以使用凭据发出实际请求。

示例配置

网站1是一个基本、匿名访问、只读方案,其中内容通过GET请求使用:

{
  "supportscredentials":false,
  "exposedheaders":[
    ""
  ],
  "supportedmethods":[
    "GET",
    "HEAD"
  ],
  "alloworigin":[
    "http://127.0.0.1:3000",
    "https://site1.com"

  ],
  "maxage:Integer": 1800,
  "alloworiginregexp":[
    "http://localhost:.*"
    "https://.*\.site1\.com"
  ],
  "allowedpaths":[
    "/content/_cq_graphql/site1/endpoint.json",
    "/graphql/execute.json.*",
    "/content/site1/.*"
  ],
  "supportedheaders":[
    "Origin",
    "Accept",
    "X-Requested-With",
    "Content-Type",
    "Access-Control-Request-Method",
    "Access-Control-Request-Headers"
  ]
}

站点2比较复杂,需要进行授权和异动(POST、PUT、DELETE)请求:

{
  "supportscredentials":true,
  "exposedheaders":[
    ""
  ],
  "supportedmethods":[
    "GET",
    "HEAD"
    "POST",
    "DELETE",
    "PUT"
  ],
  "alloworigin":[
    "http://127.0.0.1:3000",
    "https://site2.com"

  ],
  "maxage:Integer": 1800,
  "alloworiginregexp":[
    "http://localhost:.*"
    "https://.*\.site2\.com"
  ],
  "allowedpaths":[
    "/content/site2/.*",
    "/libs/granite/csrf/token.json",
  ],
  "supportedheaders":[
    "Origin",
    "Accept",
    "X-Requested-With",
    "Content-Type",
    "Access-Control-Request-Method",
    "Access-Control-Request-Headers",
    "Authorization",
    "CSRF-Token"
  ]
}

Dispatcher缓存顾虑和配置 dispatcher-caching-concerns-and-configuration

从Dispatcher 4.1.1开始,可以缓存响应标头。 这使得能够随CORS请求的资源一起缓存CORS标头,只要该请求是匿名的。

通常,在Dispatcher中缓存内容的相同注意事项也可以应用于在Dispatcher中缓存CORS响应标头。 下表定义何时可以缓存CORS标头(从而缓存CORS个请求)。

可缓存
环境
身份验证状态
解释
AEM 发布
已验证
AEM Author上的Dispatcher缓存仅限于静态的非创作资源。 这使得在AEM Author上缓存大多数资源(包括HTTP响应标头)变得困难和不实际。
AEM 发布
已验证
避免在经过身份验证的请求上缓存CORS标头。 这符合不缓存经过身份验证的请求的常见指南,因为很难确定请求用户的身份验证/授权状态将如何影响投放的资源。
AEM 发布
匿名
可以在Dispatcher中缓存的匿名请求也可以缓存其响应标头,以确保将来的CORS请求可以访问缓存的内容。 在AEM Publish 上进行的任何CORS配置更改都必须 ​后使受影响的缓存资源失效。 最佳实践要求在代码或配置部署中清除Dispatcher缓存,因为很难确定哪些缓存内容可能会受到影响。

允许CORS请求标头

若要允许所需的HTTP请求标头传递到AEM进行处理,必须在Dispatcher的/clientheaders配置中允许使用这些标头。

/clientheaders {
   ...
   "Origin"
   "Access-Control-Request-Method"
   "Access-Control-Request-Headers"
}

缓存CORS响应标头

要允许在缓存的内容上缓存并提供CORS标头,请将以下/cache /headers配置添加到AEM Publish dispatcher.any文件中。

/publishfarm {
    ...
    /cache {
        ...
        # CORS HTTP response headers
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#the_http_response_headers
        /headers {
            ...
            "Access-Control-Allow-Origin"
            "Access-Control-Expose-Headers"
            "Access-Control-Max-Age"
            "Access-Control-Allow-Credentials"
            "Access-Control-Allow-Methods"
            "Access-Control-Allow-Headers"
        }
    ...
    }
...
}

切记在对dispatcher.any文件进行更改后​ 重新启动Web服务器应用程序

可能需要完全清除缓存,以确保在更新/cache/headers配置后的下一个请求中正确缓存标头。

CORS疑难解答

日志记录在com.adobe.granite.cors下可用:

  • 启用DEBUG以查看有关CORS请求被拒绝原因的详细信息
  • 启用TRACE以查看有关通过CORS处理程序处理的所有请求的详细信息

提示:

  • 使用curl手动重新创建XHR请求,但请确保复制所有标题和详细信息,因为每个标题和详细信息都可以产生影响;某些浏览器控制台允许复制curl命令

  • 验证请求是否被CORS处理程序拒绝,而不是被身份验证、CSRF令牌过滤器、调度程序过滤器或其他安全层拒绝

    • 如果CORS处理程序使用200进行响应,但响应中不存在Access-Control-Allow-Origin标头,请查看com.adobe.granite.cors中DEBUG下的拒绝日志
  • 如果启用了CORS请求的Dispatcher缓存

    • 确保/cache/headers配置已应用于dispatcher.any,并且Web服务器已成功重新启动
    • 确保在任何OSGi或dispatcher.any配置更改后正确清除缓存。
  • 如果需要,检查请求中是否存在身份验证凭据。

支持材料

recommendation-more-help
c92bdb17-1e49-4e76-bcdd-89e4f85f45e6