概述
本节提供 CORS
的概述以及如何在 IRIS REST
服务中启用 CORS
的概述。
CORS 简介
跨域资源共享 (CORS
) 允许在另一个域中运行的脚本访问服务。
通常,当浏览器从一个域运行脚本时,它允许对同一个域进行 XMLHttpRequest
调用,但在对另一个域进行调用时不允许它们。此浏览器行为限制某人创建可滥用机密数据的恶意脚本。恶意脚本可能允许用户使用授予用户的权限访问另一个域中的信息,但随后在用户不知道的情况下,将机密信息用于其他用途。为了避免这种安全问题,浏览器一般不允许这种跨域调用。
在不使用跨域资源共享 (CORS
) 的情况下,具有访问 REST
服务的脚本的网页通常必须与提供 REST
服务的服务器位于同一域中。在某些环境中,将带有脚本的网页与提供 REST 服务的服务器放在不同的域中是很有用的。 CORS
支持这种安排。
下面提供了浏览器如何使用 CORS
处理 XMLHttpRequest
的简化描述:
- 域
DomOne
中的网页中的脚本包含对DomTwo
域中的IRIS REST
服务的XMLHttpRequest
。XMLHttpRequest
具有CORS
的自定义标头。 - 用户查看此网页并运行脚本。用户的浏览器检测到与包含网页的域不同的域的
XMLHttpRequest
。 - 用户的浏览器向
IRIS REST
服务发送一个特殊请求,该请求指示XMLHttpRequest
的HTTP
请求方法和原始网页的域,在本示例中为DomOne
。 - 如果请求被允许,则响应包含请求的信息。否则,响应仅包含指示
CORS
不允许请求的标头。
启用 REST 服务以支持 CORS 的概述
默认情况下,REST
服务不允许 CORS
标头。但是,可以启用 CORS
支持。在 REST
服务中启用对 CORS
的支持有两个部分:
- 启用
REST
服务以接受部分或所有HTTP
请求的CORS
标头。。 - 编写代码,使
REST
服务检查CORS
请求并决定是否继续。例如,可以提供一个允许列表,其中包含仅包含受信任脚本的域。IRIS
为文档目的提供了一个简单的默认实现;此默认实现允许任何CORS
请求。
重要提示:默认 CORS
标头处理不适用于处理机密数据的 REST
服务。
接受 CORS 标头
要指定 REST
服务接受 CORS
标头:
- 修改规范类以包含
HandleCorsRequest
参数。
要为所有调用启用 CORS
标头处理,请将 HandleCorsRequest
参数指定为 1
:
Parameter HandleCorsRequest = 1;
或者,要为某些调用启用 CORS
标头处理,但不是调用,请将 HandleCorsRequest
参数指定为“”
(空字符串):
Parameter HandleCorsRequest = "";
- 如果将
HandleCorsRequest
参数指定为“”
,请编辑规范类中的OpenAPI XData
块以指示哪些调用支持CORS
。具体来说,对于操作对象,添加以下属性名称和值:
"x-ISC_CORS":true
例如,OpenAPI XData
块可能包含以下内容:
"post":{
"description":"Creates a new pet in the store. Duplicates are allowed",
"operationId":"addPet",
"produces":[
"application/json"
],
...
添加 x-ISC_CORS
属性,如下所示:
"post":{
"description":"Creates a new pet in the store. Duplicates are allowed",
"operationId":"addPet",
"x-ISC_CORS":true,
"produces":[
"application/json"
],
...
- 编译规范类。此操作重新生成调度类,导致行为的实际变化。没有必要详细了解
dispatch
类,但请注意以下变化:
- 它现在包含
HandleCorsRequest
参数的值。 -
URLMap XData
块现在包含对应于修改的操作的<Route>
元素的Cors="true"
。
如果 HandleCorsRequest
参数为 0
(默认值),则对所有调用禁用 CORS
标头处理。在这种情况下,如果 REST
服务接收到带有 CORS
标头的请求,则服务会拒绝该请求。
重要提示:IRIS REST
服务支持 OPTIONS
请求(CORS
预检请求),该请求用于确定 REST
服务是否支持 CORS
。此请求始终未经身份验证发送,并由 CSPSystem
用户执行。此用户应具有 REST
服务使用的任何数据库的 READ
权限;如果没有,服务将响应 HTTP 404
错误。
定义如何处理 CORS 标头
当启用 REST
服务以接受 CORS
标头时,默认情况下,该服务接受任何 CORS
请求。 REST
服务应检查 CORS
请求并决定是否继续。例如,可以提供一个允许列表,其中包含仅包含受信任脚本的域。为此,需要:
- 创建
%CSP.REST
的子类。在这个类中,实现第一小节中描述的OnHandleCorsRequest()
方法。 - 修改规范类并重新编译,重新生成调度类。
最终结果是调度类从自定义类而不是从 %CSP.REST
继承,因此使用对 OnHandleCorsRequest()
的定义,它覆盖了默认的 CORS
标头处理。
定义 OnHandleCorsRequest()
在 %CSP.REST
的子类中,定义 OnHandleCorsRequest()
方法,该方法需要检查 CORS
请求并适当地设置响应标头。
要定义此方法,必须熟悉 CORS
协议的细节(此处不讨论)。
还需要知道如何检查请求并设置响应标头。为此,检查默认使用的方法是有用的,即 %CSP.REST
的 HandleDefaultCorsRequest()
方法。本节说明此方法如何处理源、凭据、标头和请求方法并提出变体建议。可以使用此信息来编写 OnHandleCorsRequest()
方法。
以下代码获取源并使用它来设置响应标头。一种可能的变体是根据允许列表测试来源。然后域被允许,设置响应头。如果不是,请将响应标头设置为空字符串。
代码语言:javascript复制 #; Get the origin
Set tOrigin=$Get(%request.CgiEnvs("HTTP_ORIGIN"))
#; Allow requested origin
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Origin",tOrigin)
以下几行指定应包含授权标头。
代码语言:javascript复制 #; Set allow credentials to be true
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Credentials","true")
以下行从传入请求中获取标头和请求方法。代码应测试是否允许标头和请求方法。如果允许,请使用它们来设置响应标头。如果不是,请将响应标头设置为空字符串。
代码语言:javascript复制 #; Allow requested headers
Set tHeaders=$Get(%request.CgiEnvs("HTTP_ACCESS_CONTROL_REQUEST_HEADERS"))
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Headers",tHeaders)
#; Allow requested method
Set tMethod=$Get(%request.CgiEnvs("HTTP_ACCESS_CONTROL_REQUEST_METHOD"))
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Method",tMethod)
重要提示:默认 CORS
标头处理不适用于处理机密数据的 REST
服务。
修改规范类
在定义 %CSP.REST
的自定义子类(包括 OnHandleCorsRequest()
的实现)后,执行以下操作:
- 编辑规范类中的
OpenAPI XData
块,使info
对象包含一个名为x-ISC_DispatchParent
的新属性。此属性的值必须是自定义类的完全限定名称。
例如,假设 OpenAPI XData
块如下所示:
"swagger":"2.0",
"info":{
"version":"1.0.0",
"title":"Swagger Petstore",
"description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService":"http://swagger.io/terms/",
"contact":{
"name":"Swagger API Team"
},
...
假设 %CSP.REST
的自定义子类名为 test.MyDispatchClass
。在这种情况下,将修改 XData
块,如下所示:
"swagger":"2.0",
"info":{
"version":"1.0.0",
"title":"Swagger Petstore",
"description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService":"http://swagger.io/terms/",
"x-ISC_DispatchParent":"test.MyDispatchClass",
"contact":{
"name":"Swagger API Team"
},
...
- 编译规范类。此操作重新生成调度类。会注意到该类现在扩展了自定义调度超类。因此它将使用
OnHandleCorsRequest()
方法。