You can configure hotlink protection for your Object Storage Service (OSS) bucket to prevent your resources in the bucket from unauthorized access.
Background information
The hotlink protection feature allows you to configure a Referer whitelist for a bucket and select whether to allow the empty Referer field. This way, only requests from the domain names that are included in the Referer whitelist can access data in the bucket. You can configure Referer whitelists based on the Referer header field in HTTP and HTTPS requests.
The following scenarios describe whether to use hotlink protection to verify access to OSS:
- Only anonymous requests and requests that contain signed URLs are verified.
- Requests that contain the
Authorization
header field are not verified.
- User A adds an image object named test.jpg to the https://10.10.10.10 website. When a user accesses the image on the website, the browser sends a request in which the value of the Referer header field is https://10.10.10.10. OSS allows the request because the Referer header field in the request is included in the Referer whitelist.
- User B adds the URL of the image object to the https://192.168.0.0 website without authorization. When a user accesses the image on the website, the browser sends a request in which the value of the Referer header field is https://192.168.0.0. OSS denies the request because the Referer header field in the request is not included in the Referer whitelist.
Referer configuration rules
- You can configure multiple Referers for a bucket. When you configure Referers in the OSS console, press the Enter key to separate Referers with line feeds. When you call API operations to configure Referers, use commas (,) to separate Referers.
- You can use asterisks (*) and question marks (?) as wildcards in Referers.
- An asterisk (*) can be used as a wildcard to indicate zero or multiple characters. For example, if you add *.aliyun.com to the Referer whitelist of a bucket and deny empty Referers, only HTTP or HTTPS requests in which the Referer header field contains aliyun.com are allowed to access resources in the bucket, such as help.aliyun.com and www.aliyun.com. If you add *.aliyun.com to the Referer whitelist and allow empty Referers, requests in which the Referer header field is empty are also allowed to access resources in the bucket.
- A question mark (?) can be used as a wildcard to indicate a character. If you add a Referer that contains a question mark as a wildcard character to the Referer whitelist and deny empty Referers, only HTTP or HTTPS requests in which the Referer header field is contained are allowed to access resources in the bucket. If you add a Referer that contains a question mark (?) as a wildcard character to the Referer whitelist and allow empty Referers, requests in which the Referer header field is empty are also allowed to access resources in the bucket.
- You can use backslashes (\) to escape the asterisk (*) and question mark (?) wildcards in Referers.
- By default, query strings are truncated in Referers. You can specify that query strings
cannot be truncated based on your business requirements.
For example, if you add http://www.example.com/?action=nop to a Referer whitelist, OSS uses http://www.example.com/ to compare the Referer with the request URL because query strings are truncated by default. If you want OSS to use http://www.example.com/?action=nop to compare the Referer with the request URL, set AllowTruncateQueryString to false to disable query string truncation. For more information about how to disable query string truncation, see PutBucketReferer.
Take note of the following items when you disable query string truncation:
- Query strings are not decoded.
If you use http://www.example.com/?job_id=task$01 to access OSS, the request URL may be retained as http://www.example.com/?job_id=task$01 or be URL-encoded into http://www.example.com/?job_id=task%2401. However, OSS does not decode query strings in request URLs when OSS compares Referers with request URLs. Examples:
- When the Referer is set to http://www.example.com/?job_id=task%2401, OSS denies the access from http://www.example.com/?job_id=task$01.
- When the Referer is set to http://www.example.com/?job_id=task$01, OSS denies the access from http://www.example.com/?job_id=task%2401.
- Fields contained in query strings are not case-sensitive.
When OSS compares Referers in the whitelist with request URLs, fields contained in query strings are not case-sensitive. For example, when the Referer is set to http://www.example.com/?action=nop, OSS allows the access from http://www.example.com/?ACTION=NOP.
- Fields contained in query strings are not parsed.
By default, browsers consider http://example.com/?a=b&b=c and http://example.com/?b=c&a=b as identical URLs. However, when OSS compares Referers in the whitelist with request URLs, fields contained in query strings are not parsed. Therefore, http://example.com/?a=b&b=c and http://example.com/?b=c&a=b are considered as different URLs. In other words, when the Referer is set to http://example.com/?a=b&b=c, OSS denies the access from http://example.com/?b=c&a=b.
- Query strings are not decoded.
Effects of Referer configurations
- If the Referer whitelist is empty, all requests are allowed.
- If the Referer whitelist is not empty and empty Referers are not allowed, only requests that contain the Referers specified in the whitelist are allowed.
- If the Referer whitelist is not empty and empty Referers are allowed, only requests that contain the Referers specified in the whitelist or contain empty Referers are allowed.
Use the OSS console
Use OSS SDKs
The following code provides examples on how to configure hotlink protection for a bucket by using OSS SDKs for common programming languages. For more information about how to configure hotlink protection for a bucket by using OSS SDKs for other programming languages, see Overview.
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
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 {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console.
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// Specify the bucket name. Example: examplebucket.
String bucketName = "examplebucket";
// Create an OSSClient instance.
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
List<String> refererList = new ArrayList<String>();
// Add Referers to the Referer whitelist. You can use asterisks (*) and question marks (?) as wildcards in Referers.
refererList.add("http://www.aliyun.com");
refererList.add("http://www.*.com");
refererList.add("http://www.?.aliyuncs.com");
// Configure the Referer whitelist of the bucket. If this parameter is set to true, empty Referer fields are allowed. If this parameter is set to false, empty Referer fields are not allowed.
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;
// The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console at https://ram.console.aliyun.com.
$accessKeyId = "<yourAccessKeyId>";
$accessKeySecret = "<yourAccessKeySecret>";
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
$endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
$bucket= "<yourBucketName>";
$refererConfig = new RefererConfig();
// Allow empty Referers.
$refererConfig->setAllowEmptyReferer(true);
// Add Referers to the Referer whitelist. You can use asterisks (*) and question marks (?) as wildcards in Referers.
$refererConfig->addReferer("example.com");
$refererConfig->addReferer("example.net");
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");
let OSS = require('ali-oss')
let client = new OSS({
region: '<Your region>'
accessKeyId: '<Your AccessKeyId>',
accessKeySecret: '<Your AccessKeySecret>',
bucket: '<Your bucket name>'
});
async function putBucketReferer () {
try {
let result = await client.putBucketReferer('bucket-name', true, [
'example.com',
'*.example.com'
]);
console.log(result);
} catch (e) {
console.log(e);
}
}
putBucketReferer();
# -*- coding: utf-8 -*-
import oss2
from oss2.models import BucketReferer
# The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console.
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# Set BucketReferer to True. The value of True indicates that empty Referers are allowed and the value of False indicates that empty Referers are not allowed. Then, configure the Referer whitelist.
bucket.put_bucket_referer(BucketReferer(True, ['http://aliyun.com', 'http://*.aliyuncs.com']))
using Aliyun.OSS;
using Aliyun.OSS.Common;
var endpoint = "<yourEndpoint>";
var accessKeyId = "<yourAccessKeyId>";
var accessKeySecret = "<yourAccessKeySecret>";
var bucketName = "<yourBucketName>";
// Create an OSSClient instance.
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
var refererList = new List<string>();
// Add a Referer whitelist. You can use asterisks (*) and question marks (?) as wildcards in Referers.
refererList.Add(" http://www.aliyun.com");
refererList.Add(" http://www.*.com");
refererList.Add(" http://www.?.aliyuncs.com");
var srq = new SetBucketRefererRequest(bucketName, refererList);
// Configure the Referer whitelist.
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("yourBucketName");
// Add a Referer whitelist. You can use an asterisk (*) or a question mark (?) as a wildcard character to set the Referer parameter.
ArrayList<String> referers = new ArrayList<String>();
referers.add("http://example.com");
referers.add("http://www. *.com");
referers.add("http://www.?.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 (
"fmt"
"os"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// Create an OSSClient instance.
client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
if err!=nil{
fmt.Println("Error:", err)
os.Exit(-1)
}
bucketName := "<yourBucketName>"
// Add Referers to the Referer whitelist and specify that empty Referer fields are not allowed. You can use an asterisk (*) or a question mark (?) as a wildcard to set the Referer parameter.
referers := []string{"http://www.aliyun.com",
"http://www.???.aliyuncs.com",
"http://www.*.com"}
err = client.SetBucketReferer(bucketName, referers, false)
if err!=nil{
fmt.Println("Error:", err)
os.Exit(-1)
}
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* Initialize OSS account information. */
std::string AccessKeyId = "yourAccessKeyId";
std::string AccessKeySecret = "yourAccessKeySecret";
std::string Endpoint = "yourEndpoint";
std::string BucketName = "yourBucketName";
/* Initialize resources such as network resources. */
InitializeSdk();
ClientConfiguration conf;
OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf) ;
/* Configure hotlink protection. */
SetBucketRefererRequest request(BucketName);
request.addReferer("http://example.com");
request.addReferer("https://example.com");
request.addReferer("https://www.?.example.com");
request.addReferer("https://www.*.cn");
request.setAllowEmptyReferer(false);
auto outcome = client.SetBucketReferer(request);
if (!outcome.isSuccess()) {
/* Handle exceptions. */
std::cout << "SetBucketReferer fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
ShutdownSdk();
return -1;
}
/* Release resources such as network resources. */
ShutdownSdk();
return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
const char *endpoint = "<yourEndpoint>";
const char *access_key_id = "<yourAccessKeyId>";
const char *access_key_secret = "<yourAccessKeySecret>";
const char *bucket_name = "<yourBucketName>";
void init_options(oss_request_options_t *options)
{
options->config = oss_config_create(options->pool);
/* Use a char* string to initialize the aos_string_t data type. */
aos_str_set(&options->config->endpoint, endpoint);
aos_str_set(&options->config->access_key_id, access_key_id);
aos_str_set(&options->config->access_key_secret, access_key_secret);
/* Specify whether to use CNAME. The value of 0 indicates that CNAME is not used. */
options->config->is_cname = 0;
/* Configure network parameters such as the timeout period. */
options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
/* Call the aos_http_io_initialize method in main() to initialize global resources such as networks and memory. */
if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
exit(1);
}
/* Create a memory pool to manage memory. aos_pool_t is equivalent to apr_pool_t. The code used to create a memory pool is included in the APR library. */
aos_pool_t *pool;
/* Create a memory pool. The second parameter is set to NULL. This value indicates that the pool does not inherit other memory pools. */
aos_pool_create(&pool, NULL);
/* Create and initialize options. This parameter includes global configuration information such as endpoint, access_key_id, access_key_secret, is_cname, and curl. */
oss_request_options_t *oss_client_options;
/* Allocate the memory resources in the memory pool to the options. */
oss_client_options = oss_request_options_create(pool);
/* Initialize oss_client_options. */
init_options(oss_client_options);
/* Initialize the parameters. */
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 = 0;
/* Add a Referer whitelist. You can use an asterisk (*) or a question mark (?) as a wildcard character to set the Referer parameter. */
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");
}
/* Release the memory pool. This operation releases the memory resources allocated for the request. */
aos_pool_destroy(pool);
/* Release the allocated global resources. */
aos_http_io_deinitialize();
return 0;
}
require 'aliyun/oss'
client = Aliyun::OSS::Client.new(
endpoint: 'endpoint',
access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')
bucket = client.get_bucket('my-bucket')
bucket.referer = BucketReferer.new(
allow_empty: true, whitelist: ['example.com', '*.example.com'])
Use ossutil
For more information about how to use ossutil to configure hotlink protection, see Add or modify hotlink protection configurations for a bucket.
Use the RESTful API
If your business requires a high level of customization, you can directly call RESTful APIs. To directly call an API, you must include the signature calculation in your code. For more information, see PutBucketReferer
References
- If you want to allow users that meet specified conditions to access part of or all resources in your bucket or perform specific operations on the resources, we recommend that you configure bucket policies. For example, you can configure a bucket policy to allow only users from specified IP addresses or CIDR blocks to access a specified bucket. For more information about how to configure bucket policies, see Configure bucket policies to authorize other users to access OSS resources.
- For more information about how to troubleshoot hotlink protection errors, see Referer.