You can configure hotlink protection for your Object Storage Service (OSS) bucket to prevent your resources in the bucket from unauthorized access.

Overview

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 that is included in HTTP requests and HTTPS requests.

Whether to use hotlink protection to verify access to OSS is determined based on the following rules:

  • Only anonymous requests and requests that include signed URLs are verified.
  • Requests that include the Authorization header field are not verified.
OSS determines the source from which a request is sent based on the Referer header field that is included in the request. When a browser sends a request to the web server, the Referer header field is included in the request to specify the source from which the request is sent. OSS determines whether to allow the request based on the Referer header field included in the request and the Referer whitelist that is configured for the specified bucket. If the Referer header field that is included in the request matches the Referer whitelist, the request is allowed. If the Referer header field that is included in the request does not match the Referer whitelist, the request is denied. For example, if the Referer whitelist for a bucket is set to https://10.10.10.10, OSS determines whether to allow access requests to access objects in the bucket.
  • 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, separate Referers with commas (,).
  • 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 requests or HTTPS requests in which the Referer header field includes 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 requests or HTTPS requests in which the Referer header field is included 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 are not 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. 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 included in query strings are not case-sensitive.

      When OSS compares Referers in the whitelist with request URLs, fields included in query strings are case-insensitive. For example, when the Referer is set to http://www.example.com/?action=nop, OSS allows the access from http://www.examplecom/?ACTION=NOP.

    • Fields included 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. When OSS compares Referers in the whitelist with request URLs, fields that are included 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.

Effects of Referer configurations

  • If the Referer Whitelist field is set to an asterisk (*) and empty Referers are not allowed, only requests that include a non-empty Referer are allowed.
  • If the Referer Whitelist field is set to an asterisk (*) and empty Referers are allowed, requests that include an empty Referer are allowed.
  • If the Referer Whitelist field is not set to an asterisk (*) and empty Referers are not allowed, only requests that include the Referers specified in the whitelist are allowed.
  • If the Referer Whitelist field is not set to an asterisk (*) and empty Referers are allowed, only requests that include the Referers specified in the whitelist or include empty Referers are allowed.

Use the OSS console

  1. Log on to the OSS console.
  2. In the left-side navigation pane, click Buckets. On the Buckets page, click the name of the desired bucket.
  3. In the navigation tree, choose Content Security > Hotlink Protection.
  4. On the Hotlink Protection page, turn on Hotlink Protection.
    • Enter domain names or IP addresses in the Referer Whitelist field. Separate multiple Referers with line feeds. You can use asterisks (*) and question marks (?) as wildcard characters. Example:
      • You must include the HTTP or HTTPS scheme in the domain name that you specify. For example, if you add http://www.aliyun.com to the Referer whitelist, OSS allows requests to the bucket from URLs prefixed with http://www.aliyun.com, such as http://www.aliyun.com/123 and http://www.aliyun.com.cn.
      • An asterisk (*) can be used as a wildcard to indicate zero or multiple characters. If you add *www.aliyun.com/ to the Referer whitelist, OSS allows requests to the bucket from URLs such as http://www.aliyun.com/ and https://www.aliyun.com/. If you add *.aliyun.com to the Referer whitelist, OSS allows requests to the bucket from URLs such as help.aliyun.com and www.aliyun.com.
      • A question mark (?) can be used as a wildcard to indicate a character.
      • You can add domain names or IP addresses that include a port number, such as www.example.com:8080 or 10.10.10.10:8080, to the Referer whitelist.
    • Select whether to turn on Allow Empty Referer.

      An HTTP or HTTPS request that has an empty Referer includes an empty Referer field or does not include the Referer field.

      If you turn off Allow Empty Referer, only HTTP requests or HTTPS requests that include an allowed Referer can access the objects in the bucket.

      Note By default, if you preview an MP4 object by using a bucket domain name such as bucketname.oss-cn-zhangjiakou.aliyuncs.com, the browser sends two requests. One request includes the Referer field, and the other request includes an empty Referer. You must add the bucket domain name to the Referer whitelist and turn on Allow Empty Referer. To preview a non-MP4 object by using the bucket domain name, you need to only turn on Allow Empty Referer.
    • Select whether to turn on Truncate QueryString.
  5. Click Save.

Use OSS SDKs

The following sample code provides examples on how to configure hotlink protection for a bucket by using OSS SDKs for common programming languages. To obtain the sample code that uses OSS SDKs for other programming languages to configure Referers, 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";
        // 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. 
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // Specify the name of the bucket. 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 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");
            // Configure the Referer whitelist for the bucket. If you set BucketReferer to true, empty Referer fields are allowed. If you set BucketReferer 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. 
$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 a Referer whitelist. You can use asterisks (*) and question marks (?) as wildcard characters 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");
            
const OSS = require('ali-oss')

const client = new OSS({
  // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to oss-cn-hangzhou. 
  region: 'yourregion',
  // 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. 
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  // Set yourbucketname to the name of your bucket. 
  bucket: 'yourbucketname'
});

async function putBucketReferer () {
  try {
  const 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')
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
# Set yourBucketName to the name of the bucket. 
bucket = oss2.Bucket(auth, 'https://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;
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// 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. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. 
var bucketName = "examplebucket";
// 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 wildcard characters 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 Referers to the Referer whitelist. You can use asterisks (*) and question marks (?) as wildcards in Referers. 
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. 
    // Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. Specify your actual endpoint. 
    // The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in Object Storage Service (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. 
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err!=nil{
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Set yourBucketName to the name of your bucket. 
    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 the information about the account that is used to access OSS. */
    /* 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 Resource Access Management (RAM) user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. */
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    /* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
    std::string Endpoint = "yourEndpoint";
    /* Specify the name of the bucket. Example: examplebucket. */
    std::string BucketName = "examplebucket";

    /* Initialize resources such as networks. */
    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 networks. */
    ShutdownSdk();
    return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
/* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
const char *endpoint = "yourEndpoint";
/* 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. */
const char *access_key_id = "yourAccessKeyId";
const char *access_key_secret = "yourAccessKeySecret";
/* Specify the name of the bucket. Example: examplebucket. */
const char *bucket_name = "examplebucket";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* Use a char* string to initialize data of the aos_string_t 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. A 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 network resources and memory resources. */
    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 that is used to create a memory pool is included in the APR library. */
    aos_pool_t *pool;
    /* Create a memory pool. The value of the second parameter is 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 Refers to the Referer whitelist. You can use asterisks (*) and question marks (?) as wildcards in Referers. */
    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(
  # In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # 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. 
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

# Specify the bucket name. Example: examplebucket. 
bucket = client.get_bucket('examplebucket')
# Configure the Referer allowlist of the bucket. 
bucket.referer = Aliyun::OSS::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 RESTful APIs

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

For more information about how to troubleshoot hotlink protection errors, see Referer.