All Products
Search
Document Center

Object Storage Service:Use OSS SDK for Android to authorize access

Last Updated:Aug 28, 2024

Object Storage Service (OSS) SDK for Android provides the Security Token Service (STS) authentication mode, self-signed mode, and URL signing to ensure data security on mobile devices.

Background information

When you use the STS authentication mode or self-signed mode, make sure that the callback function that you implement can return the security token and signature. If you must obtain the token and signature from the app server by sending a request in the callback function, we recommend that you call the synchronous API operations included in the network library. The callback function runs in the child thread of the request generated by the SDK and does not block the main thread.

STS authentication mode

Note

To use the STS authentication mode, you must first activate Alibaba Cloud Resource Access Management (RAM).

You can use STS to authorize temporary access to OSS. STS is a web service that provides temporary access tokens for users. You can use STS to grant temporary access credentials that have a custom validity period and custom permissions to a third-party application or a RAM user that is managed by you. For more information about STS, see What is STS?.

STS has the following benefits:

  • You need to only generate a temporary access token and send the access token to a third-party application. You do not need to provide your AccessKey pair to the third-party application. You can specify the access permissions and validity period of this token.

  • The token automatically expires after the validity period ends. Therefore, you do not need to manually revoke the access permissions of a token.

To access OSS by using temporary access credentials provided by STS, perform the following operations:

  1. 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.

  2. Use temporary access credentials to initialize OSS SDK for Android.

    String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    
    OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider("StsToken.AccessKeyId", "StsToken.SecretKeyId", "StsToken.SecurityToken");
    
    OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);                  

    When you initialize the SDK by using temporary access credentials, take note of the validity period of the STS token.

    The following sample code provides an example on how to update an STS token when the remaining validity period of the token is less than 5 minutes:

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date date = sdf.parse("<StsToken.Expiration>");
    long expiration = date.getTime() / 1000;
    // Update the STS token when its remaining validity period is less than 5 minutes. 
    if (DateUtil.getFixedSkewedTimeMillis() / 1000 > expiration - 5 * 60) {
        oss.updateCredentialProvider(new OSSStsTokenCredentialProvider("StsToken.AccessKeyId", "StsToken.SecretKeyId", "StsToken.SecurityToken"));
    }
    • Manually update the STS token

      When the STS token is about to expire, you can create another OSSClient instance or update CredentialProvider by running the following line:

      oss.updateCredentialProvider(new OSSStsTokenCredentialProvider("StsToken.AccessKeyId", "StsToken.SecretKeyId", "StsToken.SecurityToken"));                   
    • Automatically update the STS token

      If you want the SDK to automatically update the STS token, you must implement a callback in your app. The callback obtains a federation token (STS token) and returns the token to the SDK. The SDK uses the STS token to generate signatures. When the STS token needs to be updated, the SDK calls the callback to obtain a new token.

      String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
      
      OSSCredentialProvider credentialProvider = new OSSFederationCredentialProvider() {
      
          @Override
          public OSSFederationToken getFederationToken() {
          // Obtain a federation token, construct the token, and then return the token as an OSSFederationToken object. If no federation token is obtained, null is returned. 
      
              OSSFederationToken token;
              // Obtain a federation token from your server. 
              return token;
          }
      };
      
      OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);                    
      Note

      If you obtain all fields that are required to generate an STS token in other ways, you can directly return the token in the callback. In this case, you must manually update the token, and then reconfigure OSSCredentialProvider of the OSSClient instance.

      If the URL of the server from which you request a token is http://localhost:8080/distribute-token.json, the following sample response is returned:

      {
          "StatusCode": 200,
          "AccessKeyId":"STS.iA645eTOXEqP3cg3****",
          "AccessKeySecret":"rV3VQrpFQ4BsyHSAvi5NVLpPIVffDJv4LojU****",
          "Expiration":"2015-11-03T09:52:59Z",
          "SecurityToken":"CAES7QIIARKAAZPlqaN9ILiQZPS+JDkS/GSZN45RLx4YS/p3OgaUC+oJl3XSlbJ7StKpQ****"}                    

      The following sample code provides an example on how to implement OSSFederationCredentialProvider:

      OSSCredentialProvider credetialProvider = new OSSFederationCredentialProvider() {
          @Override
          public OSSFederationToken getFederationToken() {
              try {
                  URL stsUrl = new URL("http://localhost:8080/distribute-token.json");
                  HttpURLConnection conn = (HttpURLConnection) stsUrl.openConnection();
                  InputStream input = conn.getInputStream();
                  String jsonText = IOUtils.readStreamAsString(input, OSSConstants.DEFAULT_CHARSET_NAME);
                  JSONObject jsonObjs = new JSONObject(jsonText);
                  String ak = jsonObjs.getString("AccessKeyId");
                  String sk = jsonObjs.getString("AccessKeySecret");
                  String token = jsonObjs.getString("SecurityToken");
                  String expiration = jsonObjs.getString("Expiration");
                  return new OSSFederationToken(ak, sk, token, expiration);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return null;
          }
      };                    

URL signing

Usage notes

  • When you use an OSS SDK to generate a signed URL, the OSS SDK uses a specific algorithm based on the key information stored in the local computer to calculate a signature and adds the signature to a URL to ensure the validity and security of the URL. The operations performed to calculate and construct the URL are completed on the client. You do not need to send requests to the server over the network. This way, you do not need to grant specific permissions to the caller when you generate the signed URL. However, to allow third-party users to perform relevant operations on the resources authorized by the signed URL, you must make sure that the principal that calls the API operations to generate the signed URL has the corresponding permissions.

    For example, if a principal wants to upload an object by using a signed URL, you must grant the oss:PutObject permission to the principal. If a principal wants to download or preview an object by using a signed URL, you must grant the oss:GetObject permission to the principal.

  • The signed URL generated by using the following sample code may contain a plus sign (+). In this case, replace the plus sign (+) in the URL with %2B. Otherwise, the signed URL may not be used to access the object as expected.

The following sample code provides examples on how to generate signed URLs for temporary access authorization:

Generate a signed URL and use the signed URL to upload a file

  1. Generate a signed URL.

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the source object. Do not include the bucket name in the full path. Example: exampleobject.txt. 
    String objectKey = "exampleobject.txt";
    // Specify the contentType header. 
    String contentType = "application/octet-stream";
    String url = null;
    try {
        // Generate a signed URL to upload the object. 
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey);
        // Set the validity period of the signed URL to 30 minutes. 
        request.setExpiration(30*60);
        request.setContentType(contentType);    
        request.setMethod(HttpMethod.PUT);
        url = oss.presignConstrainedObjectURL(request);
        Log.d("url", url);
    } catch (ClientException e) {
        e.printStackTrace();
    }
  2. Use the signed URL to upload an object.

    // Enter the generated signed URL. 
    String url = "";
    // Specify the full path of the local file. 
    String localFile = "/storage/emulated/0/oss/examplefile";
    // Specify the contentType header. 
    String contentType = "application/octet-stream";
    // Upload the object by using the signed URL. 
    OkHttpClient client = new OkHttpClient();
    Request putRequest = new Request.Builder()
            .url(url)
            .put(RequestBody.create(MediaType.parse(contentType), new File(localFile)))
            .build();
    client.newCall(putRequest).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }
    
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            Log.d("response", response.body().string());
        }
    });

Generate a signed URL and use the signed URL to download the object

  1. Generate a signed URL.

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the source object. Do not include the bucket name in the full path. Example: exampleobject.txt. 
    String objectKey = "exampleobject.txt";
    String url = null;
    try {
        // Generate a signed URL to download the object. 
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey);
        // Set the validity period of the signed URL to 30 minutes. 
        request.setExpiration(30*60);
        request.setMethod(HttpMethod.GET);
        url = oss.presignConstrainedObjectURL(request);
        Log.d("url", url);
    } catch (ClientException e) {
        e.printStackTrace();
    }
  2. Use the signed URL to download the object.

    // Enter the generated signed URL. 
    String url = "";
    OkHttpClient client = new OkHttpClient();
    // Use the signed URL to download the object. 
    Request getRequest = new Request.Builder()
            .url(url)
            .get()
            .build();
    client.newCall(getRequest).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }
    
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.code() == 203 || response.code() >= 300) {
                Log.d("download", "fail");
                Log.d("download", response.body().string());
                return;
            }
            // The object is downloaded. 
            InputStream inputStream = response.body().byteStream();
    
            byte[] buffer = new byte[2048];
            int len;
    
            while ((len = inputStream.read(buffer)) != -1) {
                // Process the downloaded data. For example, display the image or perform a write operation on the object. 
            }
        }
    });