跨源资源共享(CORS)

Adobe Experience Manager as a Cloud Service的跨源资源共享(CORS)有助于非AEM Web资产对AEM的GraphQL API和其他AEM Headless资源进行基于浏览器的客户端调用。

TIP
以下配置是示例。 确保根据项目要求对其进行调整。

CORS要求

如果连接到AEM GraphQL API的客户端不从与AEM相同的源(也称为主机或域)提供服务,则基于浏览器的连接到AEM API需要CORS。

客户端类型
单页应用程序(SPA)
Web组件/JS
移动设备
服务器到服务器
需要CORS配置

AEM Author

在AEM Author服务上启用CORS与AEM Publish和AEM Preview服务不同。 AEM Author服务要求将OSGi配置添加到AEM Author服务的运行模式文件夹,并且不使用Dispatcher配置。

OSGi配置

AEM CORS OSGi配置工厂定义了接受CORS HTTP请求的允许标准。

客户端连接到
AEM Author
AEM 发布
AEM预览
需要CORS OSGi配置

以下示例为AEM Author (../config.author/..)定义了OSGi配置,因此该配置仅在AEM Author服务上处于活动状态。

关键配置属性包括:

  • alloworigin和/或alloworiginregexp指定了连接到AEM Web的客户端所运行的源。

  • allowedpaths指定允许来自指定源的URL路径模式。

    • 要支持AEM GraphQL持久查询,请添加以下模式:/graphql/execute.json.*
    • 要支持体验片段,请添加以下模式: /content/experience-fragments/.*
  • supportedmethods为CORS请求指定允许的HTTP方法。 要支持AEM GraphQL持久查询(和体验片段),请添加GET

  • supportedheaders包含"Authorization",因为应授权对AEM作者的请求。

  • supportscredentials设置为true,因为应授权对AEM作者的请求。

了解有关CORS OSGi配置的更多信息。

以下示例支持在AEM Author上使用AEM GraphQL持久查询。 若要使用客户端定义的GraphQL查询,请在allowedpathsPOST中将GraphQL终结点URL添加到supportedmethods

  • /ui.config/src/main/content/jcr_root/apps/wknd-examples/osgiconfig/config.author/com.adobe.granite.cors.impl.CORSPolicyImpl~graphql.cfg.json
{
  "alloworigin":[
    "https://spa.external.com/"
  ],
  "alloworiginregexp":[
  ],
  "allowedpaths": [
    "/graphql/execute.json.*",
    "/content/experience-fragments/.*"
  ],
  "supportedheaders": [
    "Origin",
    "Accept",
    "X-Requested-With",
    "Content-Type",
    "Access-Control-Request-Method",
    "Access-Control-Request-Headers",
    "Authorization"
  ],
  "supportedmethods":[
    "GET",
    "HEAD",
    "POST"
  ],
  "maxage:Integer": 1800,
  "supportscredentials": true,
  "exposedheaders":[ "" ]
}

示例OSGi配置

AEM 发布

在AEM Publish(和预览)服务上启用CORS与AEM Author服务不同。 AEM Publish服务要求将AEM Dispatcher配置添加到AEM Publish的Dispatcher配置。 AEM Publish不使用OSGi配置

在AEM Publish上配置CORS时,请确保:

  • 无法通过从AEM Publish项目的clientheaders.any文件中删除Origin标头(如果之前已添加)将Origin HTTP请求标头发送到AEM Dispatcher服务。 应从clientheaders.any文件中删除任何Access-Control-标头,由Dispatcher管理这些标头,而不是AEM Publish服务。
  • 如果您在AEM Publish服务上启用了任何CORS OSGi配置,则必须将其删除并将其配置迁移到下面列出的Dispatcher vhost配置

Dispatcher配置

必须将AEM Publish(和预览)服务的Dispatcher配置为支持CORS。

客户端连接到
AEM Author
AEM 发布
AEM预览
需要Dispatcher CORS配置

在vhost中设置CORS标头

  1. 在Dispatcher配置项目中打开AEM Publish服务的vhost配置文件,通常位于dispatcher/src/conf.d/available_vhosts/<example>.vhost

  2. 将以下<IfDefine ENABLE_CORS>...</IfDefine>块的内容复制到已启用的vhost配置文件中。

    code language-none h-17
       <VirtualHost *:80>
      ...
      <IfModule mod_headers.c>
          ################## Start of CORS configuration ##################
    
          SetEnvIfExpr "req_novary('Origin') == ''" CORSType=none CORSProcessing=false
          SetEnvIfExpr "req_novary('Origin') != ''" CORSType=cors CORSProcessing=true CORSTrusted=false
    
          SetEnvIfExpr "req_novary('Access-Control-Request-Method') == '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != ''" CORSType=invalidpreflight CORSProcessing=false
          SetEnvIfExpr "req_novary('Access-Control-Request-Method') != '' && %{REQUEST_METHOD} == 'OPTIONS' && req_novary('Origin') != ''" CORSType=preflight CORSProcessing=true CORSTrusted=false
          SetEnvIfExpr "req_novary('Origin') -strcmatch 'http://%{HTTP_HOST}*'" CORSType=samedomain CORSProcessing=false
          SetEnvIfExpr "req_novary('Origin') -strcmatch 'https://%{HTTP_HOST}*'" CORSType=samedomain CORSProcessing=false
    
          # For requests that require CORS processing, check if the Origin can be trusted
          SetEnvIfExpr "%{HTTP_HOST} =~ /(.*)/ " ParsedHost=$1
    
          ################## Adapt regex to match CORS origin(s) for your environment
          SetEnvIfExpr "env('CORSProcessing') == 'true' && req_novary('Origin') =~ m#(https://.*\.your-domain\.tld(d+?lang=zh-Hans)?$)#" CORSTrusted=true
    
          # Extract the Origin header
          SetEnvIfNoCase ^Origin$ ^(.*)$ CORSTrustedOrigin=$1
    
          # Flush If already set
          Header unset Access-Control-Allow-Origin
          Header unset Access-Control-Allow-Credentials
    
          # Trusted
          Header always set Access-Control-Allow-Credentials "true" "expr=reqenv('CORSTrusted') == 'true'"
          Header always set Access-Control-Allow-Origin "%{CORSTrustedOrigin}e" "expr=reqenv('CORSTrusted') == 'true'"
          Header always set Access-Control-Allow-Methods "GET" "expr=reqenv('CORSTrusted') == 'true'"
          Header always set Access-Control-Max-Age 1800 "expr=reqenv('CORSTrusted') == 'true'"
          Header always set Access-Control-Allow-Headers "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers" "expr=reqenv('CORSTrusted') == 'true'"
    
          # Non-CORS or Not Trusted
          Header unset Access-Control-Allow-Credentials "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"
          Header unset Access-Control-Allow-Origin "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"
          Header unset Access-Control-Allow-Methods "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"
          Header unset Access-Control-Max-Age "expr=reqenv('CORSProcessing') == 'false' || reqenv('CORSTrusted') == 'false'"
    
          # Always vary on origin, even if its not there.
          Header merge Vary Origin
    
          # CORS - send 204 for CORS requests which are not trusted
          RewriteCond expr "reqenv('CORSProcessing') == 'true' && reqenv('CORSTrusted') == 'false'"
          RewriteRule "^(.*)" - [R=204,L]
    
          # Remove Origin before sending to AEM Publish if this configuration handles the CORS
          RequestHeader unset Origin "expr=reqenv('CORSTrusted') == 'true'"
    
          ################## End of CORS configuration ##################
      </IfModule>
      ...
    </VirtualHost>
    
  3. 通过更新以下行中的正则表达式,匹配用于访问AEM Publish服务的所需源。 如果需要多个原点,请复制此行并更新每个原点/原点阵列。

    code language-none
    SetEnvIfExpr "env('CORSProcessing') == 'true' && req_novary('Origin') =~ m#(https://.*.your-domain.tld(:\d+)?$)#" CORSTrusted=true
    
    • 例如,要启用从源访问CORS,请执行以下操作:

      • https://example.com上的任何子域
      • http://localhost上的任意端口

      将该行替换为以下两行:

      code language-none
      SetEnvIfExpr "env('CORSProcessing') == 'true' && req_novary('Origin') =~ m#(https://.*\.example\.com$)#" CORSTrusted=true
      SetEnvIfExpr "env('CORSProcessing') == 'true' && req_novary('Origin') =~ m#(http://localhost(:\d+)?$)#" CORSTrusted=true
      

Dispatcher配置示例

recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4