OSS设置跨域资源共享CORS

更新时间: 2024-06-25 10:10:11

默认情况下,由于同源策略(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://help.aliyun.com/dir/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控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择数据安全 > 跨域设置

  4. 跨域设置页面,单击创建规则

  5. 创建跨域规则面板,按以下说明设置跨域规则。

    参数

    是否必须

    说明

    来源

    指定允许的跨域请求的来源。配置规则如下:

    • 允许多条匹配规则,多条规则需换行填写。

    • 域名需包含协议名,例如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回源次数增加。

  6. 单击确定

使用阿里云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

常见问题

CORS配置项常见错误

关于CORS配置项常见错误及排查方法,请参见OSS跨域资源共享(CORS)错误排除

报“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。

上一篇: 防盗链常见问题 下一篇: 设置跨域规则后调用OSS时仍然报“No 'Access-Control-Allow-Origin'”的错误
阿里云首页 对象存储 相关技术圈