This topic describes how to use a signed URL or temporary access credentials from Security Token Service (STS) to grant a third-party user permissions to upload objects directly 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.
Benefits
To address the challenge in the preceding scenario, OSS allows you to authorize third-party uploads. This way, each client can upload objects directly 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. Furthermore, you can focus on your business without worries about bandwidth and concurrency limits. You have the option to use a signed URL or temporary access credentials to grant a third-party user permissions to upload objects directly to OSS. In most cases, we recommend that you use temporary access credentials.
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 on the client to upload objects. 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 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 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 objects 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; // Specify the temporary AccessKey pair obtained from STS. $accessKeyId = "yourAccessKeyId"; $accessKeySecret = "yourAccessKeySecret"; // Specify the security token obtained from STS. $securityToken = "yourSecurityToken"; // 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. $object = "exampleobject.txt"; // Specify the string that you want to upload. $content = "Hello OSS"; try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken); // Upload the object by using the temporary access credentials obtained from STS. $ossClient->putObject($bucket, $object, $content); } catch (OssException $e) { print $e->getMessage(); }
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. This results in an invalid combined object. For more information, see Add signatures to URLs.