附註:
- 此教學課程需要存取 Oracle Cloud。若要註冊免費帳戶,請參閱開始使用 Oracle Cloud Infrastructure Free Tier 。
- 它使用 Oracle Cloud Infrastructure 憑證、租用戶及區間的範例值。完成實驗室時,請將這些值取代為您雲端環境特有的值。
使用 Shell 和 Java Code 以程式設計方式管理 Oracle Cloud Infrastructure REST API
簡介
Oracle Cloud Infrastructure (OCI) 為客戶提供雲端基礎架構,以便在雲端代管其關鍵任務應用程式。OCI 還為客戶提供透過主控台或透過 API 存取 OCI 服務的方法。為了透過 API 進行連線,客戶可以根據自己選擇的程式設計語言 (例如 Java、Python 或 Ruby) 使用 SDK。但在少數情況下,客戶無法使用 SDK,也無法使用任何程式設計語言,而是想要直接從他們無法安裝 SDK 的工具、資料庫或第三方應用程式透過 API 進行連線。以下是 REST API 的使用方式。客戶可以將 OCI 提供的 REST API 用於幾乎所有服務,並直接在工具中使用這些服務,只需更新端點並處理授權和驗證。
如今,每個組織都希望在其應用程式中運用 REST API 的強大功能,並為其客戶建立創新的產品,而無需安裝和管理任何 SDK。
在本教學課程中,我們將討論並瞭解 OCI 如何協助全球各地的組織運用 OCI 的 REST API 強大功能。在本教學課程中,我們將根據 Shell 命令檔和 Java 程式碼示範 REST API 的範例。
目標
-
根據 REST API 將連線至 OCI 租用戶的使用者,設定 OCI API 金鑰。
-
建立使用案例,以使用 REST API 將二進位檔案下載或上傳至 OCI 物件儲存。
-
設定 Shell 和 Java 應用程式、撰寫適當的程式碼以呼叫及顯示 OCI REST API。
必要條件
-
存取 Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) 中允許的 OCI 和原則。使用者應可存取想要使用 REST API 建立或更新的對應資源。
-
Shell 命令檔與 Java 應用程式開發相關知識。
-
對軟體開發之敏捷方法的基本理解。
作業 1:設定 Oracle Cloud Infrastructure API 金鑰
-
使用服務帳戶或管理員使用者登入 OCI 租用戶,並前往使用者設定值。
或
從 OCI IAM 主控台前往使用者。確定使用者具備在 OCI 上建立及更新基礎架構的所有必要存取權。
-
前往資源區段,按一下 API 金鑰和新增 API 金鑰。選取即可下載新的公用金鑰和私密金鑰、上傳您的公開金鑰或貼上您的公開金鑰。
-
將金鑰儲存在方便的位置,並依照下列頁面所示儲存配置檔案。使用 REST API 連線至您的租用戶時,將需要使用此組態檔和私密金鑰。
注意:
-
您需要相同的
configuration parameters
才能連線至 OCI 區域和租用戶。您將取代 Java 程式碼和 Shell 命令檔中的參數,因為我們深入教學課程。 -
若要從 OCI Compute 執行處理呼叫 OCI 服務,OCI 能夠以更安全的方式使用執行處理主體。避免使用使用者 API 金鑰作為最佳做法。如需詳細資訊,請參閱從執行處理呼叫服務。
-
作業 2:建立並執行 Shell 命令檔,使用 REST API 從 OCI 物件儲存上傳或放置二進位檔案
-
前往檔案系統並建立 Shell 檔案。在此範例中,檔案名稱為
PUT_OBJECT_REST_API.sh
。 -
以您選擇的編輯器開啟檔案,並將下列程式碼貼到 Shell 檔案中。
-
PUT_OBJECT_REST_API.sh
:#!/bin/bash ########################## Fill these in with your values ########################## #OCID of the tenancy calls are being made in to tenancy_ocid="ocid1.tenancy.oc1..aaaaaaaackopa" # namespace of the tenancy namespace="ocitenancyname" # OCID of the user making the rest call user_ocid="ocid1.user.oc1..aaaaaaaafelqsoffcjh" # path to the private PEM format key for this user privateKeyPath="/home/lovelesh/.oci/oci_api_key.pem" # fingerprint of the private key for this user fingerprint="72:d4:6c:f8:89" #bucket name for uplaod/ put bucket="ocibucketname" #file name for upload/ put object="test_pdf.pdf" # The REST api you want to call, with any required paramters. rest_api="/n/$namespace/b/$bucket/o/$object" # The host you want to make the call against host="objectstorage.us-ashburn-1.oraclecloud.com" # the file containing the data you want to POST to the rest endpoint body="/home/lovelesh/.oci/test_pdf.pdf" #################################################################################### # extra headers required for a POST/PUT request method="put" content_type="application/octet-stream" body_arg=(--data-binary @${body}) content_sha256="$(openssl dgst -binary -sha256 < $body | openssl enc -e -base64)"; content_sha256_header="x-content-sha256: $content_sha256" content_length="$(wc -c < $body | xargs)"; content_length_header="content-length: $content_length" headers="(request-target) date host" # add on the extra fields required for a POST/PUT headers=$headers" x-content-sha256 content-type content-length" content_type_header="content-type: $content_type"; date=`date -u "+%a, %d %h %Y %H:%M:%S GMT"` date_header="date: $date" host_header="host: $host" request_target="(request-target): $method $rest_api" # note the order of items. The order in the signing_string matches the order in the headers, including the extra POST fields signing_string="$request_target\n$date_header\n$host_header" # add on the extra fields required for a POST/PUT signing_string="$signing_string\n$content_sha256_header\n$content_type_header\n$content_length_header" signature=`printf '%b' "$signing_string" | openssl dgst -sha256 -sign $privateKeyPath | openssl enc -e -base64 | tr -d '\n'` set -x curl -v -X $(echo $method | tr [:lower:] [:upper:]) --data-binary "@$body" -sS https://$host$rest_api -H "date: $date" -H "x-content-sha256: $content_sha256" -H "content-type: $content_type" -H "content-length: $content_length" -H "Authorization: Signature version=\"1\",keyId=\"$tenancy_ocid/$user_ocid/$fingerprint\",algorithm=\"rsa-sha256\",headers=\"$headers\",signature=\"$signature\""
-
-
現在我們已經將所有程式碼貼到 shell 檔案中,讓我們努力更新所需的值並瞭解其功能。
tenancy_ocid="ocid1.tenancy.oc1..aaaaaaaackopa" ... fingerprint="72:d4:6c:f8:89"
所有這些值都負責與您的 OCI 租用戶進行安全連線。從組態檔取得這些值。
rest_api="/n/$namespace/b/$bucket/o/$object" host="objectstorage.us-ashburn-1.oraclecloud.com"
這是 rest_api 和 host 端點,依照您的需求做好準備,因為這將會對每個服務和每個服務進行變更。此處顯示的範例是 ashburn 區域 OCI 物件儲存體服務的端點。
headers=$headers" x-content-sha256 content-type content-length" content_type_header="content-type: $content_type"; date=`date -u "+%a, %d %h %Y %H:%M:%S GMT"` date_header="date: $date" host_header="host: $host" request_target="(request-target): $method $rest_api"
我們已在此建立 REST API 標頭,以及內容類型和其他必要參數。請注意,這裡有 method_type 、 date 以及 host headers 的定義,我們需要設定詳細的標頭。
signing_string="$signing_string\n$content_sha256_header\n$content_type_header\n$content_length_header" curl -v -X $(echo $method | tr [:lower:] [:upper:]) --data-binary "@$body" ...
最後,我們正在建立簽署字串,然後使用 Curl 進行 REST API 呼叫。請注意,OCI 需要簽署 API 呼叫,這也是我們在此進行 API 呼叫的原因。
-
依照您的組態更新值之後,請執行 Shell 命令檔,您應該會看到執行全部正常的命令檔,並將檔案推送至 OCI Object Storage。
注意:
-
請將 Shell 檔案權限變更為 755 或自行管理,以確定您已更新可執行的 Shell 檔案權限。
-
同樣地,您也可以使用 powershell 在 Windows 上執行此操作,或藉由安裝 WSL (Windows Subsystem for Linux) (例如 Ubuntu) 在 Windows 上使用相同的程序檔,然後在 Windows 上從 Ubuntu WSL 執行。如需詳細資訊,請參閱 Windows Subsystem for Linux 。
-
作業 3:建立並執行 Java 程式碼以使用 REST API 從 OCI 物件儲存上傳或放置二進位檔案
-
移至檔案系統並建立 java 檔案。在此範例中,檔案名稱為
PUT_OBJECT_REST_API.java
。 -
以您選擇的編輯器開啟檔案,並將下列程式碼貼到 Shell 檔案中。
-
PUT_OBJECT_REST_API.java
:import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Base64; // NOTE - Feel free to remove logging as needed. Currently logs the signing string, host, date, and response. public class PUT_OBJECT_REST_API { private static final String apiKeyFilePath = "C:\\Users\\User1\\Folder\\privatekey.pem" private static final String tenancyId = "ocid1.tenancy.oc1..aaaaaaaackopa27emaz4uteg4q7"; // OCI Tenancy ID private static final String userId = "ocid1.user.oc1..aaaaaaaafelqsoffcjq"; // OCI User ID private static final String keyFingerprint = "72:d4:6c:f8:89:74:aa"; // OCI fingerprint private static final String region = "us-ashburn-1"; // OCI Region private static final String namespace = "ocitenancyname"; // OCI bucket namespace private static final String bucketName = "ocibucketname"; // OCI bucket NAME public static void main(String[] args) { try { String filePath = "D:\\file\\location\\test_pdf.pdf"; //args.length > 0 ? args[0] : ""; // File to upload (path) PrivateKey privateKey = loadPrivateKey(apiKeyFilePath); String fileName = Paths.get(filePath).getFileName().toString(); String targetUri = "https://objectstorage." + region + ".oraclecloud.com/n/" + namespace + "/b/" + bucketName + "/o/" + fileName; HttpRequest request = buildRequest(targetUri, filePath, privateKey); HttpClient client = HttpClient.newHttpClient(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("Response status code: " + response.statusCode()); System.out.println("Response body: " + response.body()); } catch (Exception e) { e.printStackTrace(); } } private static PrivateKey loadPrivateKey(String filePath) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { String key = new String(Files.readAllBytes(Paths.get(filePath))) .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s+", ""); // Remove all whitespace byte[] decodedKey = Base64.getDecoder().decode(key); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decodedKey); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); } private static HttpRequest buildRequest(String targetUri, String filePath, PrivateKey privateKey) throws Exception { String method = "put"; String path = "/n/" + namespace + "/b/" + bucketName + "/o/" + Paths.get(filePath).getFileName(); String host = "objectstorage." + region + ".oraclecloud.com"; String date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC)); byte[] fileContent = Files.readAllBytes(Paths.get(filePath)); // Read file content as byte array String signingString = "(request-target): " + method.toLowerCase() + " " + path + "\n" + "host: " + host + "\n" + "date: " + date; System.out.println("Signing String: \n" + signingString); String signature = signRequest(privateKey, signingString); String authorizationHeader = "Signature version=\"1\",headers=\"(request-target) host date\",keyId=\"" + tenancyId + "/" + userId + "/" + keyFingerprint + "\",algorithm=\"rsa-sha256\",signature=\"" + signature + "\""; return HttpRequest.newBuilder() .uri(URI.create(targetUri)) .header("Content-Type", "application/octet-stream") .header("date", date) .header("Authorization", authorizationHeader) .PUT(HttpRequest.BodyPublishers.ofByteArray(fileContent)) .build(); } private static String signRequest(PrivateKey privateKey, String dataToSign) throws Exception { Signature signatureInstance = Signature.getInstance("SHA256withRSA"); signatureInstance.initSign(privateKey); signatureInstance.update(dataToSign.getBytes()); byte[] signature = signatureInstance.sign(); return Base64.getEncoder().encodeToString(signature); } }
-
-
現在我們把所有貼到 java 檔案中的程式碼,讓我們努力更新必要的值並瞭解其功能。
private static final String apiKeyFilePath = "C:\\Users\\User1\\Folder\\privatekey.pem" private static final String tenancyId = "ocid1.tenancy.oc1..aaaaaaaackopa27emaz4uteg4q7"; // OCI Tenancy ID private static final String userId = "ocid1.user.oc1..aaaaaaaafelqsoffcjq"; // OCI User ID private static final String keyFingerprint = "72:d4:6c:f8:89:74:aa"; // OCI fingerprint private static final String region = "us-ashburn-1"; // OCI Region private static final String namespace = "ocitenancyname"; // OCI bucket namespace private static final String bucketName = "ocibucketname"; // OCI bucket NAME
所有這些值都負責與您的 OCI 租用戶進行安全連線。從組態檔取得這些值。
String targetUri = "https://objectstorage." + region + ".oraclecloud.com/n/" + namespace + "/b/" + bucketName + "/o/" + fileName; HttpRequest request = buildRequest(targetUri, filePath, privateKey);
這是 rest_api 和主機端點,依照您的需求做好準備,因為這會針對每個服務和每個服務進行變更。此處顯示的範例是 ashburn 區域 OCI 物件儲存體服務的端點。
private static HttpRequest buildRequest
我們已建立 REST API 標頭,以及內容類型和其他必要參數。請注意,這裡有 method_type、日期及主機標頭的定義 (針對後續呼叫),我們需要詳細的標頭集。
private static String signRequest
最後,我們正在建立簽署字串,然後進行 REST API 呼叫。請注意,OCI 需要簽署 API 呼叫,這也是我們在此進行 API 呼叫的原因。
-
依照您的組態更新值之後,請執行 java 程式碼,您應該會看到所有正常執行的命令檔,並將檔案推送至 OCI Object Storage。
注意:請確定已安裝 Java 與程式碼所需的所有必要套裝程式。
相關連結
認可
- 作者 - Lovelesh Saxena (主要軟體工程架構師)
其他學習資源
瀏覽 docs.oracle.com/learn 的其他實驗室,或前往 Oracle Learning YouTube 頻道存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。
如需產品文件,請造訪 Oracle Help Center 。
Manage Oracle Cloud Infrastructure REST APIs Programmatically using Shell and Java Code
G12006-01
July 2024