是否有一种方法允许多个跨域使用Access-Control-Allow-Origin头?
我知道*,但它太开放了。我只讲几个域。
举个例子,是这样的:
Access-Control-Allow-Origin: http://domain1.example, http://domain2.example
我已经尝试了上面的代码,但它似乎不能在Firefox中工作。
是否可以指定多个域,还是只能指定一个域?
是否有一种方法允许多个跨域使用Access-Control-Allow-Origin头?
我知道*,但它太开放了。我只讲几个域。
举个例子,是这样的:
Access-Control-Allow-Origin: http://domain1.example, http://domain2.example
我已经尝试了上面的代码,但它似乎不能在Firefox中工作。
是否可以指定多个域,还是只能指定一个域?
当前回答
对于ExpressJS应用程序,您可以使用:
app.use((req, res, next) => {
const corsWhitelist = [
'https://domain1.example',
'https://domain2.example',
'https://domain3.example'
];
if (corsWhitelist.indexOf(req.headers.origin) !== -1) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
}
next();
});
其他回答
下面是一个Java web应用的解决方案,基于yesthatguy的回答。
我使用的是Jersey REST 1.x
配置web.xml以识别Jersey REST和CORSResponseFilter
<!-- Jersey REST config -->
<servlet>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.your.package.CORSResponseFilter</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.your.package</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
下面是CORSResponseFilter的代码
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;
public class CORSResponseFilter implements ContainerResponseFilter{
@Override
public ContainerResponse filter(ContainerRequest request,
ContainerResponse response) {
String[] allowDomain = {"http://localhost:9000","https://my.domain.example"};
Set<String> allowedOrigins = new HashSet<String>(Arrays.asList (allowDomain));
String originHeader = request.getHeaderValue("Origin");
if(allowedOrigins.contains(originHeader)) {
response.getHttpHeaders().add("Access-Control-Allow-Origin", originHeader);
response.getHttpHeaders().add("Access-Control-Allow-Headers",
"origin, content-type, accept, authorization");
response.getHttpHeaders().add("Access-Control-Allow-Credentials", "true");
response.getHttpHeaders().add("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS, HEAD");
}
return response;
}
}
下面的答案是针对c#的,但是这个概念应该适用于所有不同的平台。
为了允许来自web api的跨源请求,你需要允许应用程序的选项请求,并在控制器级别添加下面的注释。
[EnableCors UrlString、头、方法) 现在原点只能传递一个s字符串。因此,如果你想在请求中传递多个URL,请以逗号分隔。
UrlString = https://a.hello.com, https://b.hello.com”
AWS Lambda/ fire Gateway
有关如何在无服务器AWS Lambda和API网关上配置多个源的信息-尽管一个相当大的解决方案,但人们会觉得应该非常简单-请参阅这里:
https://stackoverflow.com/a/41708323/1624933
目前不可能在API Gateway中配置多个源,请参阅这里:https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html),但建议(在上面的回答中)是:
检查浏览器发送的Origin报头 在来源白名单上查一下 如果匹配,返回传入的Origin作为Access-Control-Allow-Origin头,否则返回占位符(默认Origin)。
简单的解决方案显然是可行的 所有(*)像这样:
exports.handler = async (event) => {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
},
body: JSON.stringify([{
但是在API网关端做这件事可能会更好(见上面的第二个链接)。
听起来,推荐的方法是让服务器从客户端读取Origin头,将其与您希望允许的域列表进行比较,如果匹配,则将Origin头的值作为响应中的Access-Control-Allow-Origin头回显给客户端。
使用.htaccess,你可以这样做:
# ----------------------------------------------------------------------
# Allow loading of external fonts
# ----------------------------------------------------------------------
<FilesMatch "\.(ttf|otf|eot|woff|woff2)$">
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin=$0
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header merge Vary Origin
</IfModule>
</FilesMatch>
这招对我很管用:
SetEnvIf Origin "^http(s)?://(.+\.)?(domain\.example|domain2\.example)$" origin_is=$0
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is
当放入。htaccess时,它肯定会工作。