為阻止其他網站引用您的OSS檔案,引起不必要的流量費用增加,您可以在Referer白名單中僅添加您自己網站的網域名稱,從而僅允許該網域名稱的網站引用您的OSS檔案。
前提條件
錯誤地配置Referer防盜鏈會導致您的網站無法正常引用您的OSS檔案,或者使用者無法在瀏覽器中直接存取您的OSS檔案。在配置之前,您需要在測試的Bucket上驗證Referer防盜鏈配置是否生效,然後再在實際使用的Bucket上配置。
注意事項
阿里雲帳號預設擁有配置Referer防盜鏈的許可權。如果您需要通過RAM使用者或者STS的方式進行配置,您必須擁有oss:PutBucketReferer
許可權。具體操作,請參見為RAM使用者授權自訂的權限原則。
操作方式
使用OSS控制台
例如,僅允許網域名稱為www.aliyun.com
的網站引用您的OSS檔案,並且允許使用者在瀏覽器中直接輸入URL訪問您的OSS檔案。具體步驟如下:
登入OSS管理主控台。
單擊Bucket 列表,然後單擊目標Bucket名稱。
在左側導覽列,選擇資料安全>防盜鏈。
在防盜鏈頁面,開啟防盜鏈開關。
在白名單 Referer,輸入以下內容。
通過控制台設定多個Referer時使用斷行符號作為分行符號分隔。
https://www.aliyun.com http://www.aliyun.com
關於Referer的配置規範,請參見Referer配置規範。
黑名單 Referer,保持為空白。
重要黑白名單同時存在時,OSS會先判斷黑名單,再判斷白名單。具體判斷流程,請參見防盜鏈的判斷邏輯。
在空 Referer地區,選擇允許。
允許:表示允許請求中不帶Referer或Referer為空白。
不允許:表示請求中必須攜帶Referer且Referer值不可為空。設定不允許空Referer後,無法在瀏覽器中直接輸入URL訪問OSS檔案。
在截斷 QueryString地區,選擇允許。
允許:OSS匹配該Referer時預設截斷QueryString。例如Referer設定為
http://www.example.com/?action=nop
,OSS匹配該Referer時預設截斷QueryString,即使用http://www.example.com/
進行匹配。不允許:OSS匹配該Referer時不截斷QueryString。例如Referer設定為
http://www.example.com/?action=nop
,OSS會使用http://www.example.com/?action=nop
進行匹配。關於QueryString的解析規則,請參見QueryString解析規則。
單擊儲存。
使用阿里雲SDK
例如,僅允許網域名稱為www.aliyun.com
的網站引用您的OSS檔案,並且允許使用者在瀏覽器中直接輸入URL訪問您的OSS檔案。配置樣本如下:
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.BucketReferer;
import java.util.ArrayList;
import java.util.List;
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";
// 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為cn-hangzhou。
String region = "cn-hangzhou";
// 建立OSSClient執行個體。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
List<String> refererList = new ArrayList<String>();
// 添加Referer白名單。Referer參數支援萬用字元星號(*)和問號(?)。
refererList.add("http://www.aliyun.com");
refererList.add("https://www.aliyun.com");
// refererList.add("http://www.help.aliyun.com");
// refererList.add("http://www.?.aliyuncs.com");
// 設定儲存空間Referer列表。設為true表示Referer欄位允許為空白,設為false表示Referer欄位不允許為空白。
BucketReferer br = new BucketReferer(true, refererList);
ossClient.setBucketReferer(bucketName, br);
} 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\OssClient;
use OSS\Core\OssException;
use OSS\Model\RefererConfig;
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$accessKeyId = getenv("OSS_ACCESS_KEY_ID");
$accessKeySecret = getenv("OSS_ACCESS_KEY_SECRET");
// Endpoint以杭州為例,其它Region請按實際情況填寫。
$endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
$bucket= "examplebucket";
$refererConfig = new RefererConfig();
// 設定允許空Referer。
$refererConfig->setAllowEmptyReferer(true);
// 添加Referer白名單。Referer參數支援萬用字元星號(*)和問號(?)。
$refererConfig->addReferer("http://wwww.aliyun.com");
$refererConfig->addReferer("https://wwww.aliyun.com");
// $refererConfig->addReferer("http://wwww.help.aliyun.com");
// $refererConfig->addReferer("http://www.?.aliyuncs.com");
try{
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
$ossClient->putBucketReferer($bucket, $refererConfig);
} 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,
authorizationV4: true,
// 填寫儲存空間名稱。
bucket: 'examplebucket'
});
async function putBucketReferer () {
try {
const result = await client.putBucketReferer(bucket, true, [
'http://www.aliyun.com',
'https://www.aliyun.com'
]);
console.log(result);
} catch (e) {
console.log(e);
}
}
putBucketReferer();
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import BucketReferer
# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# 填寫Endpoint對應的Region資訊,例如cn-hangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-hangzhou"
# yourBucketName填寫儲存空間名稱。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
# 設定允許空Referer。
allow_empty_referer = True
# 設定白名單Referer。
referers = ['http://www.aliyun.com', 'https://www.aliyun.com']
# 設定黑名單Referer。
# black_referers = ['http://example.com', 'http://*.example.com']
# 設定截斷QueryString。
allow_truncate_query_string = True
# 設定防盜鏈。
bucket.put_bucket_referer(BucketReferer(allow_empty_referer=allow_empty_referer, referers=referers, black_referers=black_referers,allow_truncate_query_string=allow_truncate_query_string))
using Aliyun.OSS;
using Aliyun.OSS.Common;
// yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數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名稱。
var bucketName = "examplebucket";
// 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。
const string region = "cn-hangzhou";
// 建立ClientConfiguration執行個體,按照您的需要修改預設參數。
var conf = new ClientConfiguration();
// 設定v4簽名。
conf.SignatureVersion = SignatureVersion.V4;
// 建立OssClient執行個體。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
c.SetRegion(region);
try
{
var refererList = new List<string>();
// 添加Referer白名單。Referer參數支援萬用字元星號(*)和問號(?)。
refererList.Add("http://www.aliyun.com");
refererList.Add("https://www.aliyun.com");
// refererList.Add("http://www.help.aliyun.com");
// refererList.Add("http://www.?.aliyuncs.com");
var srq = new SetBucketRefererRequest(bucketName, refererList);
// 設定防盜鏈。
client.SetBucketReferer(srq);
Console.WriteLine("Set bucket:{0} Referer succeeded ", bucketName);
}
catch (OssException ex)
{
Console.WriteLine("Failed with error code: {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);
}
PutBucketRefererRequest request = new PutBucketRefererRequest();
request.setBucketName("examplebucket");
// 添加Referer白名單。Referer參數支援萬用字元星號(*)和問號(?)。
ArrayList<String> referers = new ArrayList<String>();
referers.add("http://www.aliyun.com");
referers.add("https://www.aliyun.com");
// referers.add("http://www.help.aliyun.com");
// referers.add("http://www.?.aliyuncs.com");
request.setReferers(referers);
OSSAsyncTask task = oss.asyncPutBucketReferer(request, new OSSCompletedCallback<PutBucketRefererRequest, PutBucketRefererResult>() {
@Override
public void onSuccess(PutBucketRefererRequest request, PutBucketRefererResult result) {
OSSLog.logInfo("code: " + result.getStatusCode());
}
@Override
public void onFailure(PutBucketRefererRequest request, ClientException clientException, ServiceException serviceException) {
OSSLog.logError("error: "+serviceException.getRawMessage());
}
});
task.waitUntilFinished();
package main
import (
"log"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// 填寫Bucket名稱。
bucketName := "examplebucket"
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
log.Fatalf("Error creating credentials provider: %v", err)
}
// 建立OSSClient執行個體。
// yourEndpoint填寫Bucket對應的Endpoint,以華東1(杭州)為例,填寫為https://oss-cn-hangzhou.aliyuncs.com。其它Region請按實際情況填寫。
// yourRegion填寫Bucket所在地區,以華東1(杭州)為例,填寫為cn-hangzhou。其它Region請按實際情況填寫。
clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
clientOptions = append(clientOptions, oss.Region("yourRegion"))
// 設定簽名版本
clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
client, err := oss.New("yourEndpoint", "", "", clientOptions...)
if err != nil {
log.Fatalf("Error creating OSS client: %v", err)
}
var setBucketReferer oss.RefererXML
// 添加Referer白名單,且允許空Referer。Referer參數支援萬用字元星號(*)和問號(?)。
setBucketReferer.RefererList = []string{
"http://www.aliyun.com",
"https://www.aliyun.com",
"https://www.help.aliyun.com",
"http://www.?.aliyuncs.com",
}
// 添加Referer黑名單。Go SDK 2.2.8及以上版本支援添加Referer黑名單。
setBucketReferer.RefererBlacklist = &oss.RefererBlacklist{
Referer: []string{
"http://www.refuse.com",
"https://*.hack.com",
"http://ban.*.com",
"https://www.?.deny.com",
},
}
setBucketReferer.AllowEmptyReferer = true
boolFalse := false
setBucketReferer.AllowTruncateQueryString = &boolFalse
err = client.SetBucketRefererV2(bucketName, setBucketReferer)
if err != nil {
log.Fatalf("Error setting bucket referer: %v", err)
}
log.Println("Set Bucket Referer 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";
/* yourRegion填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
std::string Region = "yourRegion";
/* 填寫Bucket名稱,例如examplebucket。*/
std::string BucketName = "examplebucket";
/* 初始化網路等資源。*/
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
/* 設定防盜鏈。*/
SetBucketRefererRequest request(BucketName);
request.addReferer("http://www.aliyun.com");
request.addReferer("https://www.aliyun.com");
/* request.addReferer("https://help.aliyun.com");*/
/* request.addReferer("http://www.?.aliyuncs.com");*/
request.setAllowEmptyReferer(true);
auto outcome = client.SetBucketReferer(request);
if (!outcome.isSuccess()) {
/* 異常處理。*/
std::cout << "SetBucketReferer 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";
/* yourRegion填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
const char *region = "yourRegion";
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"));
//需要額外配置以下兩個參數
aos_str_set(&options->config->region, region);
options->config->signature_version = 4;
/* 是否使用了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;
oss_referer_config_t referer_config;
aos_str_set(&bucket, bucket_name);
aos_list_init(&referer_config.referer_list);
oss_create_and_add_refer(pool, &referer_config, "http://www.aliyun.com");
oss_create_and_add_refer(pool, &referer_config, "https://www.aliyun.com");
referer_config.allow_empty_referer = 1;
/* 添加Referer白名單。Referer參數支援萬用字元星號(*)和問號(?)。*/
resp_status = oss_put_bucket_referer(oss_client_options, &bucket, &referer_config, &resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("put bucket referer succeeded\n");
} else {
printf("put bucket referer 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')
# 設定儲存空間Referer列表。
bucket.referer = Aliyun::OSS::BucketReferer.new(
allow_empty: true, whitelist: ['http://www.aliyun.com', 'https:www.aliyun.com'])
通過SDK設定多個Referer時,使用半形逗號(,)分隔。
關於其他SDK的設定防盜鏈的程式碼範例,請參見SDK簡介。
使用命令列工具ossutil
您可以使用命令列工具ossutil來配置Referer防盜鏈,ossutil的安裝請參見安裝ossutil。
以下樣本展示了僅允許網域名稱為www.aliyun.com
的網站引用您的OSS檔案,並且允許使用者在瀏覽器中直接輸入URL訪問您的OSS檔案。
ossutil api put-bucket-referer --bucket xuelitest --referer-configuration "{\"AllowEmptyReferer\":\"true\",\"RefererList\":{\"Referer\":[\"http://www.aliyun.com\",\"https://www.aliyun.com\"]}}"
如果您想瞭解該命令的更多資訊,請參見put-bucket-referer。
Referer配置規範
在配置白名單Referer或黑名單Referer時,您需要遵循以下規範:
規範 | 說明 |
匹配Referer時,不忽略URL的Scheme | 配置為 |
Referer支援萬用字元星號(*)表示使用星號代替0個或多個字元 |
|
Referer支援萬用字元問號(?)表示使用問號代替一個字元 | 配置為 |
Referer支援帶連接埠的網域名稱或IP地址 | 配置為 |
QueryString解析規則
如果您設定不允許截斷QueryString,OSS將按照以下規則解析QueryString:
規則 | 說明 |
不解碼QueryString | 在請求URL為 |
忽略QueryString中的參數大小寫 | 在請求URL為 |
不解析QueryString中的參數 | 在請求URL為 |
相關API
以上操作方式底層基於API實現,如果您的程式自訂要求較高,您可以直接發起REST API請求。直接發起REST API請求需要手動編寫代碼計算簽名。更多資訊,請參見PutBucketReferer。