For security reasons, accessing some Object Storage Service (OSS) objects by using the default domain name of a bucket may trigger forced or automatic downloads. To preview or download these objects in a browser as intended, you must bind a custom domain name to the bucket and access the objects by using the custom domain name. Binding a custom domain name does not affect the default domain name of the bucket, which can still be used to access OSS objects as usual.
Scenarios
Preview objects: For security purposes, when you access OSS objects by using the default domain name of a bucket, OSS automatically adds a download response header. This results in the browser forcing a download of the objects. However, when you use a custom domain name to access the same objects, OSS does not add the download response header. This enables the objects to be previewed directly in the browser instead of being downloaded. For information about the effective time and scope of automatic downloads triggered by accessing OSS objects by using a default domain name of a bucket, see What do I do if an object cannot be previewed when I access the object?
Access .apk or .ipa objects: For security purposes, accessing .apk or .ipa objects by using the default domain name of a bucket results in a 400 error with the ApkDownloadForbidden error code. However, access to the same objects by using a custom domain name is not restricted. For information about the effective time and scope of restricted access triggered by accessing OSS objects by using a default domain name of a bucket, see Appendix.
Improve brand images and professionalism: Binding custom domain names to OSS buckets enhances brand identities, reinforces professionalism, and builds user trust.
Bypass domain name blocking: Some applications or platforms may block the default domain names of buckets. To ensure continued access to the resources in your OSS bucket, we recommend that you bind a custom domain name to your bucket.
Improve access convenience: A custom domain name is easier to remember than a default domain name. It simplifies access, enhances user-friendliness, and makes sharing resources more efficient.
Ensure URL persistence: After you bind a custom domain name to an OSS bucket, the same domain name can continue to be used for accessing resources, even if the storage location or service changes. This ensures the persistence of the resource URL, allowing long-term access and use of the resources.
Limitations
Custom domain names containing Chinese characters are not supported.
Custom domain names that have already been bound for image processing cannot be bound to buckets again.
Each custom domain name can be bound to only one bucket.
You can bind up to 100 custom domain names to each bucket.
The OSS console does not support binding a wildcard domain name to a bucket. For example, a domain name starting with an asterisk (*) cannot be bound to a bucket. If such a domain name is bound, all subdomains of that domain name will point to the bucket. However, when you use Alibaba Cloud CDN to accelerate access to a bucket, a wildcard domain name can be bound. In this case, the domain name will not be visible in the OSS console.
Prerequisites
An OSS bucket is created. For more information, see Create a bucket.
A custom domain name is registered. You can bind a domain name registered with a third-party provider to a bucket in Alibaba Cloud. If you do not have a domain name, you can register one by using Alibaba Cloud Domains service platform. For more information, see Register a domain name on Alibaba Cloud.
An Internet Content Provider (ICP) filing is obtained for your domain name, and real-name verification is completed for your Alibaba Cloud account if the bucket to which the domain name is to be bound is located in the Chinese mainland. For more information about IPC filings and real-name verification, see ICP filing process and FAQ about real-name verification of Alibaba Cloud accounts.
Procedure
Step 1: Bind a custom domain name
The process for binding a custom domain name to a bucket varies depending on the domain registrar and the owner account. You can query the domain registrar by accessing the Alibaba Cloud WHOIS page and check the associated owner account in the Alibaba Cloud DNS console.
Bind a domain name registered by using the current Alibaba Cloud account
To bind a custom domain name that is registered by using the current Alibaba Cloud account, perform the following steps:
Log on to the OSS console.
In the left-side navigation pane, click Buckets. On the Buckets page, find and click the desired bucket.
In the left-side navigation pane, choose Bucket Settings > Domain Names.
On the Domain Names page, click Map Custom Domain Name.
In the Map Custom Domain Name panel, enter a custom domain name without a protocol, such as
static.example.com
, and click Confirm.Add a CNAME record to map the
static.example.com
domain name to the default domain name of your bucket.Automatically add a CNAME record
Turn on the Automatically Add CNAME Record toggle.
After you turn on the toggle, the CNAME record is automatically added in Alibaba Cloud DNS, as shown in the following figure.
Manually add a CNAME record
If the Automatically Add CNAME Record toggle is turned off, perform the following steps to manually add a CNAME record in Alibaba Cloud DNS to ensure the custom domain name can take effect:
Log on to the Alibaba Cloud DNS console.
Choose Public DNS Resolution > Authoritative DNS Resolution. On the Authoritative Domain Names tab, find the desired domain name and click DNS Settings in the Actions column.
On the DNS Settings tab, click Add DNS Record. In the Add DNS Record dialog box, configure the following parameters based on your business requirements.
Parameter
Description
Example
Record Type
The type of the DNS record that you want to add. Select CNAME to map a domain name to another domain name.
CNAME
Hostname
The prefix of the domain that you want to bind.
static
DNS Request Source
The DNS line that you want to use to resolve the domain name. We recommend that you select Default for this parameter to allow the DNS system to automatically select an optimal line.
Default
Record Value
The public domain name of the bucket. The domain name of a bucket is in the <bucketname>.<endpoint> format. For more information about the public endpoints of different regions, see Regions and endpoints.
examplebucket.oss-cn-hangzhou.aliyuncs.com
TTL Period
The update interval of the record. Keep the default value.
NoteThe TTL period setting may experience a delay before taking effect. The actual time in use will prevail.
10 Minutes
Click OK.
The CNAME record appears in the DNS record list of the domain name in Alibaba Cloud DNS, as shown in the following figure.
Bind a domain name registered by using a different Alibaba Cloud account
To bind a domain name registered by using Alibaba Cloud A to an OSS bucket created by using Alibaba Cloud B, perform the following steps:
Use Alibaba Cloud Account B to obtain the hostname and value of the TXT record.
Log on to the OSS console.
In the left-side navigation pane, click Buckets. On the Buckets page, find and click the desired bucket.
In the left-side navigation pane, choose Bucket Settings > Domain Names.
On the Domain Names page, click Map Custom Domain Name.
In the Map Custom Domain Name panel, enter the domain name registered by using Alibaba Cloud A without a protocol, such as
static.example.com
, and copy the values of the Hostname and Record Value parameters.
Use Alibaba Cloud Account A to add a TXT record.
Log on to the Alibaba Cloud DNS console.
In the domain name list, find the desired domain name and click DNS Settings in the Actions column.
On the DNS Settings tab, click Add DNS Record. In the Add DNS Record dialog box, configure the following parameters based on your business requirements.
Parameter
Description
Example
Record Type
The type of the DNS record that you want to add. In this topic, TXT is selected.
TXT
Hostname
The root domain name is automatically filled. You do not need to manually enter the root domain part.
If the domain name you want to bind is a root domain name, enter
_dnsauth
. For example, if the root domain name isexample.com
, enter_dnsauth
in the text box.If the domain name you want to bind is a subdomain name, enter the value in the
_dnsauth.<domain prefix>
format. For example, if the subdomain name isstatic.example.com
, enter_dnsauth.static
in the text box.
_dnsauth.static
DNS Request Source
The DNS line that you want to use to resolve the domain name. We recommend that you select Default for this parameter to allow the DNS system to automatically select an optimal line.
Default
Record Value
The CnameToken of the TXT record that was recorded earlier by using Alibaba Cloud Account B.
b0d777f7ccddeae93358d908ed59****
TTL
The update interval of the record. Keep the default value.
NoteThe TTL period setting may experience a delay before taking effect. The actual time in use will prevail.
10 Minutes
Click OK.
Log on to the OSS console by using Alibaba Cloud Account B and go to the Map Custom Domain Name panel. Click Verify Domain Name Ownership.
Use Alibaba Cloud Account A to add a CNAME record.
On the Domain Name Resolution page, find the domain name and click DNS Settings in the Actions column.
On the DNS Settings tab, click Add DNS Record. In the Add DNS Record dialog box, configure the following parameters based on your business requirements.
Parameter
Description
Example
Record Type
The type of the DNS record that you want to add. In this topic, CNAME is selected.
CNAME
Hostname
The host record.
If the domain name is a root domain name, such as
example.com
, enter @ in the text box.If the domain name is a subdomain name, enter the prefix of the subdomain name in the text box. For example, if the subdomain name is
static.example.com
, enter static.
static
DNS Request Source
The DNS line that you want to use to resolve the domain name. We recommend that you select Default for this parameter to allow the DNS system to automatically select an optimal line.
Default
Record Value
The public domain name of the bucket. The domain name of a bucket is in the <bucketname>.<endpoint> format. For more information about the public endpoints of different regions, see Regions and endpoints.
examplebucket.oss-cn-hangzhou.aliyuncs.com
TTL
The update interval of the record. Keep the default value.
NoteThe TTL period setting may experience a delay before taking effect. The actual time in use will prevail.
10 Minutes
Click OK.
Bind a domain name registered with a third-party provider to a bucket
To bind a domain name registered with a third-party provider to an OSS bucket, perform the following steps:
In the OSS console, generate a hostname and value as a TXT record.
Log on to the OSS console.
In the left-side navigation pane, click Buckets. On the Buckets page, find and click the desired bucket.
In the left-side navigation pane, choose Bucket Settings > Domain Names.
On the Domain Names page, click Map Custom Domain Name.
In the Map Custom Domain Name panel, enter the custom domain name registered with a third-party provider without a protocol, such as
static.example.com
and copy the values of the Hostname and Record Value parameters.
On the DNS platform of your domain registrar, use the parameters described in the following table to add a TXT record.
Parameter
Description
Example
Record Type
The type of the DNS record that you want to add. In this topic, TXT is selected.
TXT
Hostname
If the DNS platform automatically populates the root domain name, you do not need to manually enter the root domain part.
If the domain name you want to bind is a root domain name, enter
_dnsauth
. For example, if the root domain name isexample.com
, enter_dnsauth
in the text box.If the domain name you want to bind is a subdomain name, enter the value in the
_dnsauth.<domain prefix>
format. For example, if the subdomain name isstatic.example.com
, enter_dnsauth.static
in the text box.
_dnsauth.static
Record Value
The CnameToken of the TXT record that was recorded earlier from OSS.
b0d777f7ccddeae93358d908ed59****
Return to the Map Custom Domain Name panel in the OSS console. Click Verify Domain Name Ownership.
On the DNS platform of your domain registrar, use the parameters described in the following table to add a CNAME record.
Parameter
Description
Example
Record Type
The type of the DNS record that you want to add. In this step, CNAME is selected.
CNAME
Hostname
The host record.
If the domain name is a root domain name, such as
example.com
, enter @ in the text box.If the domain name is a subdomain name, enter the prefix of the subdomain name in the text box. For example, if the subdomain name is
static.example.com
, enter static.
static
Record Value
The public domain name of the bucket. The domain name of a bucket is in the <bucketname>.<endpoint> format. For more information about the public endpoints of different regions, see Regions and endpoints.
examplebucket.oss-cn-hangzhou.aliyuncs.com
Step 2: Verify the custom domain name
After you bind a custom domain name to a bucket, any user request made by using the custom domain name will be resolved to the default domain name of the bucket through DNS. To verify the DNS records of the custom domain name, you can run the nslookup
or dig
command.
nslookup
Replace static.example.com
in the following command with your actual domain name and run the command:
nslookup -type=CNAME static.example.com
If the command output displays the public domain name of your bucket, the DNS records have taken effect.
dig
Replace static.example.com
in the following command with your actual domain name and run the command:
dig CNAME static.example.com
If the command output displays the public domain name of your bucket, the DNS records have taken effect.
Step 3: Use the custom domain name
After the DNS records of a custom domain name take effect, you can construct a URL by using the HTTP protocol and the custom domain name, which includes the signature and validity period. The URL format is:http://YourDomain/ObjectName?Signature
. You can then use this URL to access objects in your OSS bucket.
Obtain a signed URL.
Use the OSS console
Log on to the OSS console.
In the left-side navigation pane, click Buckets. On the Buckets page, click the name of the desired bucket.
In the left-side navigation tree, choose
.On the Objects page, click the name of the desired object.
In the View Details panel, select the custom domain name that is bound to the bucket in the Custom Domain Name field, retain the default settings for other parameters, and then click Copy Object URL.
Use ossbrowser
ossbrowser allows you to perform the same object-level operations as the OSS console. To obtain a signed URL, follow the on-screen instructions in ossbrowser.
Use the custom domain name to log on to ossbrowser.
Obtain the URL of the desired object.
Use OSS SDKs
You can use the custom domain name to create an OssClient instance and generate a signed URL.
Java
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import java.net.URL; import java.util.Date; public class Demo { public static void main(String[] args) throws Throwable { // Specify the custom domain name. Example: static.example.com. String endpoint = "http://static.example.com"; // Specify the ID of the region that maps to the endpoint. Example: cn-hangzhou. String region = "cn-hangzhou"; // Obtain access credentials from environment variables. Before you run the sample code, make sure that the environment variables are configured. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Create an OSSClient instance. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); // Set this parameter to true to enable CNAME. clientBuilderConfiguration.setSupportCname(true); // Explicitly declare the use of the V4 signature algorithm clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour. Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // Generate a signed URL that allows HTTP GET requests.In this example, no additional request headers are specified. Other users can access relevant content directly by using the browser. String bucketName = "examplebucket"; String objectName = "demo.png"; URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration); System.out.println(url); } 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(); } } } }
Python
# -*- coding: utf-8 -*- import oss2 from oss2.credentials import EnvironmentVariableCredentialsProvider # Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider()) # Specify the ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4. region = "cn-hangzhou" # Specify the custom domain name. Example: static.example.com. endpoint = 'http://static.example.com' # Specify the name of your bucket. bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region, is_cname=True) # Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. object_name = 'exampledir/exampleobject.txt' # Generate a signed URL that is used to download the object. In this example, the validity period of the URL is 600 seconds. # By default, OSS identifies forward slashes (/) in the full path of an object as escape characters in the signing process. Therefore, the signed URL cannot be directly used. # Set the slash_safe parameter to True. This way, OSS does not identify the forward slashes (/) in the full path of the object as escape characters, and the signed URL can be directly used. url = bucket.sign_url('GET', object_name, 600, slash_safe=True, params=params) print('The signed URL is:', url)
Node.js
const OSS = require("ali-oss"); // Specify a function used to generate a signed URL async function generateSignatureUrl(fileName) { // Obtain the signed URL const client = await new OSS({ // Use a custom domain name as the endpoint of a bucket to access the bucket endpoint: 'http://static.example.com', // Obtain the credentials for access to OSS from environment variables. Before you execute the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. accessKeyId: process.env.OSS_ACCESS_KEY_ID, accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET, bucket: 'examplebucket', // Set yourRegion to 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: 'oss-cn-hangzhou', authorizationV4: true, cname: true }); return await client.signatureUrlV4('GET', 3600, { headers: {} // Specify the request headers based on the actual request headers }, fileName); } // Call the function and pass in the object name generateSignatureUrl('yourFileName').then(url => { console.log('Generated Signature URL:', url); }).catch(err => { console.error('Error generating signature URL:', err); });
Go
package main import ( "context" "flag" "log" "time" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials" ) // Specify the global variables. var ( region string // Region in which the bucket is located. bucketName string // Name of the bucket. objectName string // Name of the object. ) // Specify the init function used to initialize command line parameters. func init() { flag.StringVar(®ion, "region", "", "The region in which the bucket is located.") flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.") flag.StringVar(&objectName, "object", "", "The name of the object.") } func main() { // Parse command line parameters. flag.Parse() // Check whether the name of the bucket is specified. if len(bucketName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, bucket name required") } // Check whether the region is specified. if len(region) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, region required") } // Check whether the object is specified. if len(objectName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, object name required") } // Load the default configurations and specify the credential provider and region. cfg := oss.LoadDefaultConfig(). WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()). WithRegion(region). WithEndpoint("http://static.example.com"). WithUseCName(true) // Create an OSS client. client := oss.NewClient(cfg) // Generate a signed URL for the GetObject request. result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), //RequestPayer: oss.Ptr("requester"), // 指定请求者身份 }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to get object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // If you specify request headers when you generate a signed URL that allows HTTP GET requests, make sure that the request headers are included in the GET request initiated by using the signed URL. This prevents request failures and signature errors. log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } }
Use ossutil
Use the custom domain name to generate a signed URL for your object by running the presign command.
ossutil presign oss://examplebucket/exampleobject.txt --endpoint "http://static.example.com” --addressing-style "cname"
To enable the ossutil command to automatically use a custom domain name, instead of manually specifying it each time, add the custom domain name to the configuration file.
Access the signed URL in a browser.
API operations
For more information about the API operation that you can call to create a CNAME token for domain ownership verification, see CreateCnameToken.
For more information about the API operation that you can call to query CNAME tokens, see GetCnameToken.
For more information about the API operation that you can call to bind a custom domain name to a bucket, see PutCname.
For more information about the API operation that you can call to query all CNAME records that point to the domain names of a bucket, see ListCname.
For more information about the API operation that you can call to delete a CNAME record of a bucket, see DeleteCname.
For more information about the API operation that you can call to add a TXT record or a CNAME record, see AddDomainRecord.
What to do next
Access an OSS object over HTTPS
By default, access over HTTPS is not supported for a custom domain name if no SSL certificate is configured. When you attempt to access an object by using a custom domain name over HTTPS, the browser will display an insecure connection warning. To enable HTTPS access for the OSS object, an SSL certificate must be configured for the custom domain name.
Access an OSS object by using a non-signed and permanently valid URL
If the URL that you obtain is in the tttp://YourDomainName/ObjectName
format, it does not include a signature or expiration time. To use this URL to access an object, make sure the access control list (ACL) of the object is public-read. However, a public-read setting allows any Internet user to access the object, potentially leading to data leaks and increased costs. For enhanced security, we recommend that you use a URL that includes a signature and expiration time.
You can use one of the following methods to set the ACL of an object:
Set the ACL of an object to public-read: You can set the ACL of an OSS object to public-read, making its URL permanently accessible to anyone. To restrict access from unauthorized websites, enable hotlink protection for the OSS object.
Accelerate the retrieval of OSS objects: To ensure secure access control for an OSS object, you can set its ACL to private. The public-read option is exclusively supported when the object is accessed over Alibaba Cloud CDN. This makes the URL of the object permanently accessible to anyone. To restrict access from unauthorized websites, enable hotlink protection for the OSS object.
Prevent unauthorized use of OSS objects by other websites
By default, OSS objects can be accessed and displayed by any website, potentially leading to unnecessary request and downstream traffic fees. To mitigate this, enable hotlink protection by configuring a Referer blacklist or whitelist. This restricts access to your OSS objects, ensuring only authorized websites can display them. Once enabled, unauthorized websites will be blocked, preventing additional fees and protecting your resources.
Host static websites on OSS
To use OSS as a static website server for storing and delivering static files such as HTML objects, CSS objects, or JavaScript objects over the Internet, you must bind a custom domain name to the OSS bucket and configure the static website hosting feature for the bucket.
Enhance OSS object download speeds across regions
For example, if your OSS objects are stored in China (Hangzhou), Alibaba Cloud CDN can accelerate access to these objects for users in other regions. When Alibaba Cloud CDN is enabled, OSS objects are cached at regional points of presence (POPs). Users accessing these objects are automatically routed to the nearest POP, ensuring faster and more efficient downloads.
We recommend that you use the CDN domain name for downloads to benefit from accelerated access and the default domain name of your bucket for uploads to optimize performance across regions.
Optimize long-distance transmission of OSS objects
For example, if your OSS objects are stored in China (Hangzhou), users accessing them from outside the Chinese mainland may encounter slow uploads and downloads. To enhance cross-border access speed and stability, you can enable transfer acceleration. This feature helps map a custom domain name to the OSS-accelerated domain name of your bucket, improving performance.