默认情况下,由于同源策略(Same-Origin Policy)的限制,网页浏览器在执行JavaScript时会限制跨域请求,只允许请求同一域或源的资源。跨域资源共享CORS(Cross-Origin Resource Sharing)简称跨域访问,允许网页浏览器向不同域或源的服务器发起跨域请求。通过跨域设置可以实现在您的网站上使用JavaScript请求非同源的OSS对象链接而不会出现跨域问题。
同源检测
跨域访问是浏览器出于安全考虑而设置的一个限制,即同源策略,是用于隔离潜在恶意文件的关键安全机制。当A、B两个网站属于不同域时,来自于A网站页面中的JavaScript代码访问B网站时,浏览器会拒绝该访问。
同协议、同域名(或IP)以及同端口视为同域。两个页面的协议、域名和端口(如果指定了端口)相同,则视为同源。下表给出了相对http://www.aliyun.com/org/test.html
的同源检测示例:
URL | 访问是否成功 | 原因 |
http://www.aliyun.com/org/other.html | 是 | 协议、域名、端口相同 |
http://www.aliyun.com/org/internal/page.html | 是 | 协议、域名、端口相同 |
https://www.aliyun.com/page.html | 否 | 协议不同(HTTPS) |
http://www.aliyun.com:22/dir/page.html | 否 | 端口不同(22) |
http://www.alibabacloud.com/help/other.html | 否 | 域名不同 |
从上表中可以看出,协议、域名或者端口不同的情况下,浏览器会拒绝该来源的访问。如果要允许这些来源的访问,需要设置跨域规则。
注意事项
每个Bucket最多可以配置20条跨域规则。
当OSS收到一个跨域请求(或者OPTIONS请求)时,会读取Bucket对应的CORS规则,然后进行相应的权限检查。OSS会依次检查每一条规则,使用第一条匹配的规则来允许请求并返回对应的Header。如果所有规则都匹配失败,则不附加任何CORS相关的Header。
如果您开启了CDN加速,并且需要进行跨域访问时,您需要在CDN控制台配置跨域规则。具体步骤,请参见CDN如何配置跨域资源共享(CORS)。
CORS规则
OSS支持根据需求灵活配置CORS规则,实现允许或者拒绝相应的跨域请求。CORS规则仅用来决定是否附加CORS相关的Header,是否拦截跨域请求由浏览器决定。
以下两种情况需选中返回Vary: Origin以避免本地缓存错乱。
选中返回Vary: Origin后,可能会造成浏览器访问次数或者CDN回源次数增加。
同时存在CORS和非CORS请求
例如实际请求中在<img>标签下发起非CORS请求,在fetch下发起CORS请求。
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>CORS Test</title> </head> <body> <!--非CORS请求--> <img src="https://examplebucket.oss-cn-beijing.aliyuncs.com/exampleobject.txt" alt=""> <script> <!--CORS请求--> fetch("https://examplebucket.oss-cn-beijing.aliyuncs.com/exampleobject.txt").then(console.log) </script> </body> </html>
Origin头存在多种可能值
例如实际应用中指定允许的跨域请求来源Origin头为
http://www.example.com
以及https://www.example.org
。
操作步骤
使用OSS控制台
登录OSS管理控制台。
单击Bucket 列表,然后单击目标Bucket名称。
在左侧导航栏,选择数据安全 > 跨域设置。
在跨域设置页面,单击创建规则。
在创建跨域规则面板,按以下说明设置跨域规则。
参数
是否必须
说明
来源
是
指定允许的跨域请求的来源。配置规则如下:
允许多条匹配规则,多条规则需换行填写。
域名需包含协议名,例如HTTP、HTTPS。
支持通配符星号(*),每条匹配规则最多允许使用一个星号(*)。
如果域名使用的不是默认端口,还需要携带端口号。例如
https://www.example.com:8080
。
域名配置示例如下:
匹配指定域名时,填写完整域名,例如
https://www.example.com。
匹配泛二级域名,可使用通配符星号(*)。例如
https://*.example.com。
匹配所有域名,可直接填写通配符星号(*)。
允许 Methods
是
指定允许的跨域请求方法。
允许 Headers
否
指定允许跨域请求的响应头。配置规则如下:
格式为key:value,例如
content-type:text/plain
,大小写不敏感。允许多条匹配规则,多条规则需换行填写。
支持通配符星号(*),每条匹配规则最多允许使用一个星号(*)。建议没有特殊需求的情况下设置为星号(*)。
暴露 Headers
否
指定允许用户从应用程序中访问的响应头,例如一个JavaScript的XMLHttpRequest对象。不允许使用星号(*)通配符。
建议暴露的常见Headers如下:
x-oss-request-id
在您使用OSS服务遇到问题时,请凭借此Request ID请求技术支持协助排查并解决您遇到的问题。
ETag
可用于检查Object内容是否发生变化。
缓存时间(秒)
否
指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。
返回 Vary: Origin
否
配置是否返回
Vary: Origin Header
。如果实际应用中同时存在CORS和非CORS请求,或者Origin头有多种可能值时,建议选中返回 Vary: Origin以避免本地缓存错乱。
重要选中返回 Vary: Origin后,可能会造成浏览器访问次数或者CDN回源次数增加。
单击确定。
使用阿里云SDK
以下仅列举常见SDK的跨域设置的代码示例。关于其他SDK的跨域设置的代码示例,请参见SDK简介。
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.SetBucketCORSRequest;
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
SetBucketCORSRequest request = new SetBucketCORSRequest(bucketName);
// 每个存储空间最多允许设置10条跨域规则。
ArrayList<SetBucketCORSRequest.CORSRule> putCorsRules = new ArrayList<SetBucketCORSRequest.CORSRule>();
SetBucketCORSRequest.CORSRule corRule = new SetBucketCORSRequest.CORSRule();
ArrayList<String> allowedOrigin = new ArrayList<String>();
// 指定允许跨域请求的来源。
allowedOrigin.add( "http://example.com");
ArrayList<String> allowedMethod = new ArrayList<String>();
// 指定允许的跨域请求方法(GET/PUT/DELETE/POST/HEAD)。
allowedMethod.add("GET");
ArrayList<String> allowedHeader = new ArrayList<String>();
// 是否允许预取指令(OPTIONS)中Access-Control-Request-Headers头中指定的Header。
allowedHeader.add("x-oss-test");
ArrayList<String> exposedHeader = new ArrayList<String>();
// 指定允许用户从应用程序中访问的响应头。
exposedHeader.add("x-oss-test1");
// AllowedOrigins和AllowedMethods最多支持一个星号(*)通配符。星号(*)表示允许所有的域来源或者操作。
corRule.setAllowedMethods(allowedMethod);
corRule.setAllowedOrigins(allowedOrigin);
// AllowedHeaders和ExposeHeaders不支持通配符。
corRule.setAllowedHeaders(allowedHeader);
corRule.setExposeHeaders(exposedHeader);
// 指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。
corRule.setMaxAgeSeconds(10);
// 最多允许10条规则。
putCorsRules.add(corRule);
// 已存在的规则将被覆盖。
request.setCorsRules(putCorsRules);
// 指定是否返回Vary: Origin头。指定为TRUE,表示不管发送的是否为跨域请求或跨域请求是否成功,均会返回Vary: Origin头。指定为False,表示任何情况下都不会返回Vary: Origin头。
// request.setResponseVary(Boolean.TRUE);
ossClient.setBucketCORS(request);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
use OSS\Model\CorsConfig;
use OSS\Model\CorsRule;
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 填写Bucket名称,例如examplebucket。
$bucket= "examplebucket";
$corsConfig = new CorsConfig();
$rule = new CorsRule();
// 设置允许跨域请求的响应头。AllowedHeader可以设置多个,每个AllowedHeader中最多只能使用一个通配符星号(*)。
// 建议无特殊需求时设置AllowedHeader为星号(*)。
$rule->addAllowedHeader("*");
// 设置允许用户从应用程序中访问的响应头。ExposeHeader可以设置多个,ExposeHeader中不支持使用通配符星号(*)。
$rule->addExposeHeader("x-oss-header");
// 设置允许的跨域请求的来源。AllowedOrigin可以设置多个,每个AllowedOrigin中最多只能使用一个通配符星号(*)。
$rule->addAllowedOrigin("https://example.com:8080");
$rule->addAllowedOrigin("https://*.aliyun.com");
// 设置AllowedOrigin为星号(*)时,表示允许所有域的来源。
//$rule->addAllowedOrigin("*");
// 设置允许的跨域请求方法。
$rule->addAllowedMethod("POST");
// 设置浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。
$rule->setMaxAgeSeconds(10);
// 每个Bucket最多支持添加10条规则。
$corsConfig->addRule($rule);
// 设置是否返回Vary: Origin头,取值为false表示任意情况下均不返回Vary: Origin头
$corsConfig->setResponseVary(false);
try{
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
);
$ossClient = new OssClient($config);
// 已存在的规则将被覆盖。
$ossClient->putBucketCors($bucket, $corsConfig);
} catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . ": OK" . "\n");
const OSS = require('ali-oss');
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'yourRegion',
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
// 填写Bucket名称。
bucket: 'yourBucket'
});
const rules = [{
// 指定允许跨域请求的来源,支持通配符星号(*),表示允许所有的来源域。
allowedOrigin: 'http://example.com',
// 指定允许的跨域请求方法,支持GET、PUT、DELETE、POST和HEAD方法。
allowedMethod: 'GET',
// 指定允许跨域请求的响应头。建议无特殊情况下将此项设置为通配符星号(*)。
allowedHeader: '*',
// 指定允许用户从应用程序中访问的响应头,例如一个JavaScript的XMLHttpRequest对象。不允许使用通配符星号(*)。
exposeHeader: 'Content-Length',
// 指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。
maxAgeSeconds: '30'
},
];
// 最多允许设置10条跨域资源共享规则。如果配置了相同的规则,则已存在的规则将被覆盖。
client.putBucketCORS("yourBucket", rules).then((r) => {
console.log(r);
});
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import BucketCors, CorsRule
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# 填写Bucket名称,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
rule = CorsRule(allowed_origins=['*'],
allowed_methods=['GET', 'HEAD'],
allowed_headers=['*'],
max_age_seconds=1000)
# 已存在的规则将被覆盖。
bucket.put_bucket_cors(BucketCors([rule]))
using Aliyun.OSS;
using Aliyun.OSS.Common;
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称,例如examplebucket。
var bucketName = "examplebucket";
// 创建OSSClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
var request = new SetBucketCorsRequest(bucketName);
var rule1 = new CORSRule();
// 指定允许跨域请求的来源。
rule1.AddAllowedOrigin("http://example.com");
// 指定允许的跨域请求方法(GET/PUT/DELETE/POST/HEAD)。
rule1.AddAllowedMethod("POST");
// AllowedHeaders和ExposeHeaders不支持通配符。
rule1.AddAllowedHeader("*");
// 指定允许用户从应用程序中访问的响应头。
rule1.AddExposeHeader("x-oss-test");
// 最多允许10条规则。
request.AddCORSRule(rule1);
var rule2 = new CORSRule();
// AllowedOrigins和AllowedMethods最多支持一个星号(*)通配符。星号(*)表示允许所有的域来源或者操作。
rule2.AddAllowedOrigin("http://example.net");
rule2.AddAllowedMethod("GET");
// 是否允许预取指令(OPTIONS)中Access-Control-Request-Headers头中指定的Header。
rule2.AddExposeHeader("x-oss-test2");
// 指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。
rule2.MaxAgeSeconds = 100;
request.AddCORSRule(rule2);
// 设置跨域资源共享规则。
client.SetBucketCors(request);
Console.WriteLine("Set bucket:{0} Cors succeeded ", bucketName);
}
catch (OssException ex)
{
Console.WriteLine("Failed with error info: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
Console.WriteLine("Failed with error info: {0}", ex.Message);
}
package main
import (
"fmt"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"os"
)
func main() {
// yourBucketName填写Bucket名称。
bucketName := "yourBucketName"
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 创建OSSClient实例。
// yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
isTrue := true
rule1 := oss.CORSRule{
AllowedOrigin: []string{"*"},
AllowedMethod: []string{"PUT", "GET", "POST"},
AllowedHeader: []string{},
ExposeHeader: []string{},
MaxAgeSeconds: 100,
}
rule2 := oss.CORSRule{
AllowedOrigin: []string{"http://www.a.com", "http://www.b.com"},
AllowedMethod: []string{"GET"},
AllowedHeader: []string{"Authorization"},
ExposeHeader: []string{"x-oss-test-01", "x-oss-test-02"},
MaxAgeSeconds: 100,
}
put := oss.PutBucketCORS{}
put.CORSRules = []oss.CORSRule{rule1,rule2}
put.ResponseVary = &isTrue
// 设置跨域资源共享规则。
err = client.SetBucketCORSV2(bucketName, put)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
fmt.Println("Set Success")
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* 初始化OSS账号信息。*/
/* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
std::string Endpoint = "yourEndpoint";
/* 填写Bucket名称,例如examplebucket。*/
std::string BucketName = "examplebucket";
/* 初始化网络等资源。*/
InitializeSdk();
ClientConfiguration conf;
/* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
SetBucketCorsRequest request(BucketName);
/* 设置跨域资源共享规则。*/
auto rule1 = CORSRule();
/* 指定允许跨域请求的来源。*/
rule1.addAllowedOrigin("http://example.com");
/* 指定允许跨域请求方法(GET/PUT/POST/DELETE/HEAD)。*/
rule1.addAllowedMethod("POST");
/* 是否允许预取指令(OPTIONS)中Access-Control-Request-Headers头中指定的Header。*/
rule1.addAllowedHeader("*");
/* 指定允许用户从应用程序中访问的响应头。*/
rule1.addExposeHeader("x-oss-test");
/* 最多指定10条规则。*/
request.addCORSRule(rule1);
auto rule2 = CORSRule();
rule2.addAllowedOrigin("http://example.net");
rule2.addAllowedMethod("GET");
rule2.addExposeHeader("x-oss-test2");
rule2.setMaxAgeSeconds(100);
request.addCORSRule(rule2);
auto outcome = client.SetBucketCors(request);
if (!outcome.isSuccess()) {
/* 异常处理。*/
std::cout << "SetBucketCors fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* 释放网络等资源。*/
ShutdownSdk();
return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
/* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
const char *endpoint = "yourEndpoint";
/* 填写Bucket名称,例如examplebucket。*/
const char *bucket_name = "examplebucket";
void init_options(oss_request_options_t *options)
{
options->config = oss_config_create(options->pool);
/* 用char*类型的字符串初始化aos_string_t类型。*/
aos_str_set(&options->config->endpoint, endpoint);
/* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
/* 是否使用了CNAME。0表示不使用。*/
options->config->is_cname = 0;
/* 用于设置网络相关参数,比如超时时间等。*/
options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
/* 在程序入口调用aos_http_io_initialize方法来初始化网络、内存等全局资源。*/
if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
exit(1);
}
/* 用于内存管理的内存池(pool),等价于apr_pool_t。其实现代码在apr库中。*/
aos_pool_t *pool;
/* 重新创建一个内存池,第二个参数是NULL,表示没有继承其它内存池。*/
aos_pool_create(&pool, NULL);
/* 创建并初始化options,该参数包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全局配置信息。*/
oss_request_options_t *oss_client_options;
/* 在内存池中分配内存给options。*/
oss_client_options = oss_request_options_create(pool);
/* 初始化Client的选项oss_client_options。*/
init_options(oss_client_options);
/* 初始化参数。*/
aos_string_t bucket;
aos_table_t *resp_headers = NULL;
aos_status_t *resp_status = NULL;
aos_list_t cors_rule_list;
oss_cors_rule_t *cors_rule1 = NULL, *cors_rule2 = NULL;
aos_str_set(&bucket, bucket_name);
aos_list_init(&cors_rule_list);
cors_rule1 = oss_create_cors_rule(pool);
aos_list_add_tail(&cors_rule1->node, &cors_rule_list);
oss_create_sub_cors_rule(pool, &cors_rule1->allowed_origin_list, "allowed_origin_1_1");
oss_create_sub_cors_rule(pool, &cors_rule1->allowed_origin_list, "allowed_origin_1_1");
oss_create_sub_cors_rule(pool, &cors_rule1->allowed_method_list, "PUT");
oss_create_sub_cors_rule(pool, &cors_rule1->allowed_method_list, "GET");
oss_create_sub_cors_rule(pool, &cors_rule1->allowed_head_list, "Authorization");
oss_create_sub_cors_rule(pool, &cors_rule1->expose_head_list, "expose_head_1_1");
oss_create_sub_cors_rule(pool, &cors_rule1->expose_head_list, "expose_head_1_1");
cors_rule2 = oss_create_cors_rule(pool);
aos_list_add_tail(&cors_rule2->node, &cors_rule_list);
oss_create_sub_cors_rule(pool, &cors_rule2->allowed_origin_list, "allowed_origin_2_1");
oss_create_sub_cors_rule(pool, &cors_rule2->allowed_origin_list, "allowed_origin_2_2");
oss_create_sub_cors_rule(pool, &cors_rule2->allowed_method_list, "PUT");
oss_create_sub_cors_rule(pool, &cors_rule2->allowed_method_list, "GET");
oss_create_sub_cors_rule(pool, &cors_rule2->allowed_head_list, "Authorization");
oss_create_sub_cors_rule(pool, &cors_rule2->expose_head_list, "expose_head_2_1");
oss_create_sub_cors_rule(pool, &cors_rule2->expose_head_list, "expose_head_2_2");
/* 设置跨域资源共享规则。*/
resp_status = oss_put_bucket_cors(oss_client_options, &bucket, &cors_rule_list, &resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("put bucket cors succeeded\n");
} else {
printf("put bucket cors failed\n");
}
/* 释放内存池,相当于释放了请求过程中各资源分配的内存。*/
aos_pool_destroy(pool);
/* 释放之前分配的全局资源。*/
aos_http_io_deinitialize();
return 0;
}
require 'aliyun/oss'
client = Aliyun::OSS::Client.new(
# Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
access_key_id: ENV['OSS_ACCESS_KEY_ID'],
access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)
# 填写Bucket名称,例如examplebucket。
bucket = client.get_bucket('examplebucket')
# 设置跨域资源共享规则。
bucket.cors = [
Aliyun::OSS::CORSRule.new(
# 指定允许跨域请求的来源,例如http://example.com。
:allowed_origins => ['http://example.com', 'http://example.net'],
# 指定允许的跨域请求的HTTP方法(GET/PUT/DELETE/POST/HEAD)。
:allowed_methods => ['PUT', 'POST', 'GET'],
# 在OPTIONS预取指令中允许的header,例如x-oss-test。
:allowed_headers => ['x-oss-test'],
# 指定允许用户从应用程序中访问的响应头。
:expose_headers => ['x-oss-test1'],
# 指定浏览器对特定资源的预取(OPTIONS)请求返回结果的缓存时间,单位为秒。
:max_age_seconds => 100)
]
使用命令行工具ossutil
关于使用ossutil跨域设置的具体操作, 请参见添加或修改CORS配置。
使用REST API
如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutBucketCors。
常见问题
报“No 'Access-Control-Allow-Origin'”错误
关于出现该错误的原因及解决方案,请参见设置跨域规则后调用OSS时仍然报“No 'Access-Control-Allow-Origin'”的错误。
使用CDN域名访问OSS遇到跨域问题
如果您使用CDN域名访问OSS遇到跨域问题,需在CDN控制台配置跨域规则。具体操作,请参见CDN如何配置跨域资源共享(CORS)。
发送跨域请求时报错Access-Control-Allow-Origin不能为*
报错Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
时,您可以将OSS中Access-Control-Allow-Origin
的值修改为具体的域名,或在前端代码中设置xhr.withCredentials = false;
来解决此问题。详情请参见发送跨域请求时报错Access-Control-Allow-Origin不能为*。
为什么配置了两条跨域规则,没有都生效?
如果您配置了两条跨域规则,OSS会依次检查每一条规则,使用第一条匹配的规则来允许请求并返回对应的Header。