Accessing OBS from App Clients
Context
OBS is widely used as the storage for web apps and mobile apps (Android and iOS). When accessing OBS from Android or iOS apps, do not directly save access keys (AK and SK), which may be cracked by hacker software, and as a result, data stored in the cloud storage may be stolen or even tampered with. To better protect data and prevent data leakage and unauthorized access after attacks, you are advised to use the following two methods. Method 1 is recommended.
Method 1: Using Temporary Access Keys and Security Token Obtained from IAM to Access OBS
By accessing OBS using temporary access keys and security token obtained from IAM, you can directly upload data to OBS from app clients, and download data from OBS. Figure 1 describes the process.
Prerequisites
A bucket has been created on OBS Console.
You have configured the bucket to be read/written privately, or read publicly and written privately.
For details, see Creating a Bucket and Creating a Custom Bucket Policy.
Role Analysis
- App client: A mobile app of an end user. An app client sends a registration or login request to the app server, and accesses OBS to upload or download data.
- App server: A backend provided by developers of Android or iOS apps. An app server manages user accounts and authorization.
- OBS: A HUAWEI CLOUD object storage service that processes data requests from mobile apps.
- IAM: HUAWEI CLOUD Identity and Access Management that generates a temporary credential.
Workflow
- An app client requests a temporary credential for data upload from an app server.
- The app server requests a temporary credential from IAM.
- IAM returns a temporary credential to the app server.
- The app server returns the AK, SK and token to the app client.
- The app client uses OBS SDKs to upload data to and download data from OBS.
Procedure
- Obtain the OBS SDK and IAM SDK.
Obtain the required SDKs in different languages from the corresponding developer guides listed in SDK Overview.
- Simulate the app server to request the AK/SK corresponding to the temporary credential from IAM and request IAM to return the temporary credential.
Perform the following operations:
- Obtain the user's IAM token.
Obtain the token by following the instructions provided in Obtaining a User Token Through Password Authentication. For Java SDK, see IAM Java SDK Demo.
- Obtain the temporary AK, SK and token based on a request with the token and policy parameters.
Obtain the access keys and token by following the instruction provided in Obtaining a Temporary Access Key and SecurityToken Through a Token. For Java SDK, see IAM Java SDK Demo.
Example: Request for restricting the user to upload data only to a specific directory of an OBS bucket based on the IAM fine-grained policy.
{ "auth":{ "identity":{ "policy":{ "Version":"1.1", "Statement":[STS { "Action":[ "obs:object:PutObject" ], "Resource":[ "obs:*:*:object:hi-company/APPClient/APP-1/*" ], "Effect":"Allow" } ] }, "token":{ "duration-seconds":900, "id":"MIIDkgYJKoZIhvcNAQcCoIIDgzCCA38CAQExDTALMEXXXXX..." }, "methods":[ "token" ] } } } - Obtain the user's IAM token.
- Initialize the OBS Client.
Initialization example:
- For Android apps
private static final String endPoint = "https://your-endpoint"; private static final String ak = "*** Provide your Access Key ***"; private static final String sk = "*** Provide your Secret Key ***"; private static final String token = "*** Provide your Secret Key ***"; private static ObsClient obsClient; // Create an ObsClient instance. ObsConfiguration config = new ObsConfiguration(); config.setSocketTimeout(30000); config.setConnectionTimeout(10000); config.setEndPoint(endPoint); obsClient = new ObsClient(ak, sk,token,config); // Use the instance to access OBS. // Close ObsClient. obsClient.close();
- For iOS apps
NSString *endPoint = @"your-endpoint"; NSString *SK = @"*** Provide your Secret Key ***"; NSString *AK = @"*** Provide your Access Key ***"; // Initialize identity authentication. OBSStaticCredentialProvider *credentailProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK]; securityTokencredentailProvider.securityToken = @"*** Provide your Security Token ***"; // Initialize service configuration. OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentailProvider]; // Perform initialization. clientOBSClient *client = [[OBSClient alloc] initWithConfiguration:conf];
- For JavaScript web apps
// AMD is not introduced. Use the constructor to create an ObsClient instance: var obsClient = new ObsClient({ access_key_id: '*** Provide your Access Key ***', secret_access_key: '*** Provide your Secret Key ***', security_token: '*** Provide your STS Token ***' server : 'https://your-endpoint'}); // Use the new ObsClient to access OBS. // AMD is introduced. Use the injected constructor to create an ObsClient instance: var obsClient; define(['ObsClient'], function(ObsClient){ obsClient = new ObsClient({ access_key_id: '*** Provide your Access Key ***', secret_access_key: '*** Provide your Secret Key ***', security_token: '*** Provide your STS Token ***' server : 'https://your-endpoint' }); // Use the instance to access OBS});
- For Android apps
Method 2: Using a Presigned URL to Access OBS
Each request initiated by an app client applies for a presigned URL from the app server. The validity period of the presigned URL is determined by the app server. Figure 2 describes the process.
Prerequisites
- A bucket has been created on OBS Console.
You have configured the bucket to be read/written privately, or read publicly and written privately.
For details, see Creating a Bucket and Creating a Custom Bucket Policy.
- Access keys (AK and SK) have been obtained.
The presigned URL is generated using the access keys. For details about how to obtain access keys, see Access Keys (AK/SK). The user who uses the access keys (AK and SK) needs to have the minimum required permissions. For details about how to authorize the permissions, see Creating a User and Granting OBS Permissions.
Role Analysis
- App client: A mobile app of an end user. An app client requests presigned URLs from the app server, and accesses OBS to upload or download data.
- App server: A backend provided by developers of Android or iOS apps. An app server manages credential information and issue presigned URLs.
- OBS: A HUAWEI CLOUD object storage service that processes data requests from mobile apps.
- An app client requests a presigned URL from an app server.
Access keys (AK and SK) are not required for accessing OBS from the app client. But a presigned URL must be obtained from the app server before accessing OBS, and required information must be carried in the URL, including the request type, resource path, and resource name. For example, an upload request needs to indicate that the URL is for uploading data. In the URL, the upload path and object name are specified. Similarly, a URL for downloading data should contain the name of the object to be downloaded.
For details about how to compute a presigned URL, see Authentication of Signature in a URL.
- The app server stores access keys (AK and SK). After verifying that the client is valid, the app server generates a presigned URL using the stored access keys (AK and SK), in accordance with the operation type and resources to be accessed by the client. A sample URL:
https://examplebucket.obs.cn-north-4.myhuaweicloud.com/objectkey?AccessKeyId=AccessKeyID&Expires=1532779451&Signature=0Akylf43Bm3mD1bh2rM3dmVp1Bo%3D
- The app client obtains the URL and uses it to upload or download data.
The URL contains information such as the AK, signature, validity period, and resources. Anyone who has the URL can perform related operations. OBS receives the request and verifies the signature, deeming that the operation is performed by the user who issues the URL. For example, if a URL carrying signature information is constructed for downloading an object, anyone who has the URL can download the object, but the URL is valid only before the expiration time specified by Expires. If temporary access keys are used, the URL will be valid within the validity period of the access keys or before the time specified by the minimum value of Expires. With the signature contained in a presigned URL, users can be authenticated to perform predefined operations, even if they have no SK.
Procedure
- Configure an app server.
- Obtain the SDK.
Obtain the required SDKs in different languages from the corresponding developer guides listed in SDK Overview.
- Generate the code for issuing a presigned URL.
The following example describes how to use Java for development on the app server.
The app server needs to identify whether a common request header or a user-defined request header is used based on the operation type, and add the header to the computing for generating a presigned URL.
- For details about common request headers, see Constructing a Request.
- For details about user-defined request headers, see the corresponding API Reference. For example, for PUT upload, see Uploading Objects - PUT.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
//Endpoint of the requested bucket String endPoint = "http://your-endpoint"; //Provide your AK and SK. String ak = "*** Provide your Access Key ***"; String sk = "*** Provide your Secret Key ***"; //Create an ObsClient instance. ObsClient obsClient = new ObsClient(ak, sk, endPoint); //Define the expiration time, in seconds. long expireSeconds = 3600L; //Specify the requested operation. TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.PUT, expireSeconds); //Specify the bucket name and object name involved in this operation. request.setBucketName("bucketname"); request.setObjectKey("objectname"); TemporarySignatureResponse response = obsClient.createTemporarySignature(request); //The presigned URL is returned, and you can print the following URL information: System.out.println(response.getSignedUrl());
For more information and code samples, see Accessing OBS Using a Temporary URL.
- Obtain the SDK.
- Use the presigned URL to initiate a request for accessing OBS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
public class Demo extends Activity { private static String bucketName = "my-obs-bucket-demo"; private static String objectKey = "my-obs-object-key-demo"; private static OkHttpClient httpClient; private static StringBuffer sb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sb = new StringBuffer(); /* * Constructs a client instance with your account for accessing OBS */ httpClient = new OkHttpClient.Builder().followRedirects(false).retryOnConnectionFailure(false) .cache(null).build(); final TextView tv = (TextView)findViewById(R.id.tv); tv.setText("Click to start test"); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { tv.setClickable(false); AsyncTask<Void, Void, String> task = new DownloadTask(); task.execute(); } }); } class DownloadTask extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) { try { /* * You need to construct an object upload request and send it to the app server to generate a presigned URL for accessing OBS. * If the response result is stored in response, obtain the URL using the getSignedUrl() method. */ sb.append("Uploading a new object to OBS from a file\n\n"); Request.Builder builder = new Request.Builder(); // Use a PUT request to upload an object. Request httpRequest = builder.url(response.getSignedUrl()).put(RequestBody.create(MediaType.parse(contentType), "Hello OBS".getBytes("UTF-8"))).build(); Call c = httpClient.newCall(httpRequest); Response res = c.execute(); sb.append("\tStatus:" + res.code()); if (res.body() != null) { sb.append("\tContent:" + res.body().string() + "\n"); } res.close(); /* * You need to construct an object download request and send it to the app server to generate a presigned URL for accessing OBS. * If the response result is stored in response, obtain the URL using the getSignedUrl() method. */ sb.append("Downloading an object\n\n"); Request.Builder builder = new Request.Builder(); // Use a GET request to download an object. Request httpRequest = builder.url(response.getSignedUrl()).get().build(); OkHttpClient httpClient = new OkHttpClient.Builder().followRedirects(false).retryOnConnectionFailure(false).cache(null).build(); Call c = httpClient.newCall(httpRequest); Response res = c.execute(); System.out.println("\tStatus:" + res.code()); if (res.body() != null) { sb.append("\tContent:" + res.body().string() + "\n"); } res.close(); return sb.toString(); } catch (Exception e) { sb.append("\n\n"); sb.append(e.getMessage()); return sb.toString(); } finally { if (httpClient != null) { try { /* * Close obs client */ httpClient.close(); } catch (IOException e) { } } } } @Override protected void onPostExecute(String result) { TextView tv = (TextView)findViewById(R.id.tv); tv.setText(result); tv.setOnClickListener(null); tv.setMovementMethod(ScrollingMovementMethod.getInstance()); } } }
Last Article: Performance Optimization
Next Article: Accessing OBS Through an NGINX Reverse Proxy


Did this article solve your problem?
Thank you for your score!Your feedback would help us improve the website.