This topic describes how to use a signed URL or temporary access credentials from Security Token Service (STS) to grant a third-party user the permissions to directly upload objects to Object Storage Service (OSS).
Background information
In a standard client/server system architecture, the server is responsible for receiving and processing requests from the client, and OSS is used as a backend storage service. In that case, the client sends the objects to upload to the application server. Then, the server forwards the objects to OSS. In this process, objects are transmitted twice: from the client to the server and from the server to OSS. In the case of bursts of access requests, the server must provide sufficient bandwidth resources for multiple clients to upload objects simultaneously. This presents a challenge to the architecture scalability.
To address the challenge in the preceding scenario, OSS allows you to authorize third-party upload. This way, each client can directly upload objects to OSS without transmitting them to the server. This reduces the costs of application servers and maximizes the OSS capability to process large amounts of data. This way, you can focus on your business without worries about bandwidth and concurrency limits. Currently, you can grant third-party users the permissions to upload objects to OSS by using temporary access credentials from STS or a signed URL.
Method comparison
Method | Description | Scenario |
Use temporary access credentials to authorize third-party users to upload objects to OSS | When a user or an application needs to access your OSS resources, you can issue temporary access credentials with specific permissions. The temporary access credentials consist of an AccessKey pair and a security token. The AccessKey pair consists of an AccessKey ID and an AccessKey secret. You can use temporary access credentials to grant users the permissions to upload objects to OSS within a specific period of time. | Authorize third-party applications to access specific resources or restrict the permissions of RAM users |
Use a signed URL to authorize third-party users to upload objects to OSS | A signed URL is a pre-signed HTTP(s) URL that contains information, such as the operations to perform on an OSS object and the validity period. After you provide the signed URL to a third party, the third party can use the URL to directly upload an object to a specific OSS bucket without exposing the long-term Access Key pair. | Users want to directly upload objects to OSS in a web application, or allow anonymous users to upload objects, but need to control the upload time and object name. |
Use temporary access credentials to authorize third-party users to upload objects to OSS
In most object upload scenarios, we recommend that you use Security Token Service (STS) SDKs to obtain temporary access credentials on the application server, and then use the temporary access credentials and OSS SDKs to upload objects from the client directly to OSS. The client can reuse the temporary access credentials on the application server to generate a signature. This is suitable for scenarios in which multipart upload and resumable upload are used to upload large objects. However, frequent calls to STS may cause throttling. In this case, we recommend that you cache the temporary access credentials and renew them before the validity period ends. For more information, see What is STS?
Obtain temporary access credentials.
The temporary access credentials consist of an AccessKey pair and a security token. The AccessKey pair consists of an AccessKey ID and an AccessKey secret. The validity period of temporary access credentials is in seconds. The minimum validity period of temporary access credentials is 900 seconds. The maximum validity period of temporary access credentials is the maximum session duration specified for the current role. For more information, see Specify the maximum session duration for a RAM role.
You can use one of the following methods to obtain temporary access credentials:
Method 1:
Call the AssumeRole operation to obtain temporary access credentials.
Method 2:
Use STS SDKs to obtain temporary access credentials. For more information, see STS SDK overview.
Use temporary access credentials to authorize a third-party user to upload objects.
The following sample code provides examples on how to use temporary access credentials to authorize a third-party user to upload an object to OSS by using OSS SDKs for common programming languages. For more information about how to perform this operation by using OSS SDKs for other programming languages, see Overview.
Java
import com.aliyun.oss.*; import com.aliyun.oss.model.PutObjectRequest; import com.aliyun.oss.common.auth.*; import java.io.File; public class Demo { public static void main(String[] args) throws Throwable { // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_SESSION_TOKEN environment variables are configured. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path. String objectName = "exampleobject.txt"; // Specify the full path of the local file. String pathName = "D:\\examplefile.txt"; // Create an OSSClient instance. OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); try { // Specify the full path of the local file. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs. PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(pathName)); ossClient.putObject(putObjectRequest); } 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
<?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; // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_SESSION_TOKEN environment variables are configured. $accessKeyId = getenv("OSS_ACCESS_KEY_ID"); $accessKeySecret = getenv("OSS_ACCESS_KEY_SECRET"); $securityToken = getenv("OSS_SESSION_TOKEN"); // 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. $endpoint = "yourEndpoint"; // Specify the name of the bucket. $bucket= "examplebucket"; // Specify the full path of the object. Do not include the bucket name in the full path of the object. $object = "exampleobject.txt"; // Specify the string that you want to upload as an object. $content = "Hello OSS"; try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken); // Upload the string to the object by using the temporary access credentials obtained from STS. $ossClient->putObject($bucket, $object, $content); } catch (OssException $e) { print $e->getMessage(); }
Node.js
const axios = require("axios"); const OSS = require("ali-oss"); // Use the temporary access credentials to initialize an OSSClient instance on the client. The instance is used to authorize temporary access to OSS resources. const getToken = async () => { // Specify the address that is used by the client to obtain the temporary access credentials. await axios.get("http://localhost:8000/sts").then((token) => { 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: 'oss-cn-hangzhou', accessKeyId: token.data.AccessKeyId, accessKeySecret: token.data.AccessKeySecret, stsToken: token.data.SecurityToken, // Specify the name of the bucket. bucket: "examplebucket", // Refresh the temporary access credentials. refreshSTSToken: async () => { const refreshToken = await axios.get("http://localhost:8000/sts"); return { accessKeyId: refreshToken.AccessKeyId, accessKeySecret: refreshToken.AccessKeySecret, stsToken: refreshToken.SecurityToken, }; }, }); // Use the temporary access credentials to upload objects to OSS. // Specify the full path of the object. Do not include the bucket name in the full path. Example: exampleobject.jpg. // Specify the full path of the local file. Example: D:\\example.jpg. client.put('exampleobject.jpg', 'D:\\example.jpg').then((res)=>{console.log(res)}).catch(e=>console.log(e)) }); }; getToken()
Python
# -*- coding: utf-8 -*- import oss2 from oss2.credentials import EnvironmentVariableCredentialsProvider # 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. endpoint = 'https://oss-cn-hangzhou.aliyuncs.com' # Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_SESSION_TOKEN environment variables are configured. auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider()) # Specify the name of the bucket. bucket_name = 'examplebucket' # Specify the full path of the object and the string that you want to upload. Do not include the bucket name in the full path. object_name = 'exampleobject.txt' # Initialize the bucket based on the StsAuth instance. bucket = oss2.Bucket(auth, endpoint, bucket_name) # Upload the object. result = bucket.put_object(object_name, "hello world") print(result.status)
Go
package main import ( "fmt" "github.com/aliyun/aliyun-oss-go-sdk/oss" "os" ) func main() { // Obtain temporary access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_SESSION_TOKEN environment variables are configured. provider, err := oss.NewEnvironmentVariableCredentialsProvider() if err != nil { fmt.Println("Error:", err) os.Exit(-1) } // 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. client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider)) if err != nil { fmt.Println("Error:", err) os.Exit(-1) } // Specify the name of the bucket. Example: examplebucket. bucketName := "examplebucket" // Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. objectName := "exampledir/exampleobject.txt" // Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt. filepath := "D:\\localpath\\examplefile.txt" bucket,err := client.Bucket(bucketName) // Use the temporary access credentials obtained from STS to grant the third-party user permissions to upload objects. err = bucket.PutObjectFromFile(objectName,filepath) if err != nil { fmt.Println("Error:", err) os.Exit(-1) } fmt.Println("upload success") }
Use a signed URL to authorize third-party users to upload objects to OSS
For simple object upload scenarios, you can use OSS SDKs on the application server to obtain a signed URL that is required to call the PutObject operation. Then, the client can use the signed URL to upload an object without using OSS SDKs. This solution is not suitable for multipart upload and resumable upload. The application server generates a signed URL for each part and returns the signed URL to the client. This increases the number of interactions with the application server and the complexity of network requests. In addition, the client may modify the content or order of the parts, which results in an invalid combined object. For more information, see Create a signed URL by using signature V1.
A validity period must be specified for STS temporary access credentials and a signed URL. When you use temporary access credentials to generate a signed URL that is used to perform operations, such as object upload and download, the minimum validity period takes precedence. For example, you can set the validity period of your temporary access credentials to 1,200 seconds and the validity period of the signed URL generated by using the credentials to 3,600 seconds. In this case, the signed URL cannot be used to upload objects after the STS temporary access credentials expire, even if the signed URL is within its validity period.