Android SDK提供了STS鑒權模式、自簽名模式以及簽名URL的方式,用於保障移動終端的安全性。
背景資訊
無論是STS鑒權模式還是自簽名模式,您實現的回呼函數都需要保證調用時Token、Signature的返回結果。如果您需要實現向業務Server擷取Token、Signature的網路請求,建議調用網路程式庫的同步介面。回調都是在SDK發起具體請求時,在請求的子線程中執行,所以不會阻塞主線程。
STS鑒權模式
使用STS模式授權需要先開通阿里雲存取控制RAM服務。
OSS可以通過阿里雲STS(Security Token Service)進行臨時授權訪問。阿里雲STS是為雲端運算使用者提供臨時存取權杖的Web服務。通過STS,您可以為第三方應用或子使用者(即使用者身份由您自己管理的使用者)頒發一個自訂時效和許可權的訪問憑證。關於STS的更多資訊,請參見STS介紹。
STS的優勢如下:
您無需透露您的長期密鑰(AccessKey)給第三方應用,只需產生一個存取權杖並將令牌交給第三方應用。您可以自訂這個令牌的存取權限及有效期間限。
您無需關心許可權撤銷問題,存取權杖到期後自動失效。
通過STS臨時授權訪問OSS的步驟如下:
擷取臨時訪問憑證
臨時訪問憑證包括臨時存取金鑰(AccessKey ID和AccessKey Secret)和安全性權杖(SecurityToken)。臨時訪問憑證有效時間單位為秒,最小值為900,最大值以當前角色設定的最大會話時間為準。更多資訊,請參見設定RAM角色最大會話時間。
您可以通過以下兩種方式擷取臨時訪問憑證。
方式一
通過調用STS服務的AssumeRole介面擷取臨時訪問憑證。
方式二
通過各語言STS SDK擷取臨時訪問憑證。
使用臨時訪問憑證初始化SDK
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);
通過臨時訪問憑證初始化SDK時,需要注意StsToken的有效時間。
以下代碼用於在判斷StsToken的有效時間小於5分鐘時對StsToken進行更新:
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; // 如果StsToken即將到期,有效時間小於5分鐘,則更新StsToken。 if (DateUtil.getFixedSkewedTimeMillis() / 1000 > expiration - 5 * 60) { oss.updateCredentialProvider(new OSSStsTokenCredentialProvider("StsToken.AccessKeyId", "StsToken.SecretKeyId", "StsToken.SecurityToken")); }
手動更新StsToken
當判斷StsToken即將到期時,您可以重新構造OSSClient,也可以通過如下方式更新CredentialProvider:
oss.updateCredentialProvider(new OSSStsTokenCredentialProvider("StsToken.AccessKeyId", "StsToken.SecretKeyId", "StsToken.SecurityToken"));
自動更新StsToken
如果您期望SDK自動更新StsToken,那麼您需要在SDK的應用中實現回調。通過您實現回調的方式去擷取Federation Token(即StsToken),SDK會使用此StsToken來進行加簽處理,並在需要更新時主動調用此回調來擷取StsToken。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; OSSCredentialProvider credentialProvider = new OSSFederationCredentialProvider() { @Override public OSSFederationToken getFederationToken() { // 擷取FederationToken,並將其構造為OSSFederationToken對象返回。如果因某種原因FederationToken擷取失敗,伺服器則直接返回null。 OSSFederationToken token; // 從您的伺服器中擷取Token。 return token; } }; OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);
說明如果您已經通過其他方式擷取了StsToken所需的各個欄位,也可以在回調中直接返回StsToken。但您需要手動處理StsToken的更新,且更新後重新設定該OSSClient執行個體的OSSCredentialProvider。
假設您訪問的Server地址為http://localhost:8080/distribute-token.json,則返回的資料如下:
{ "StatusCode": 200, "AccessKeyId":"STS.iA645eTOXEqP3cg3****", "AccessKeySecret":"rV3VQrpFQ4BsyHSAvi5NVLpPIVffDJv4LojU****", "Expiration":"2015-11-03T09:52:59Z", "SecurityToken":"CAES7QIIARKAAZPlqaN9ILiQZPS+JDkS/GSZN45RLx4YS/p3OgaUC+oJl3XSlbJ7StKpQ****"}
實現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
注意事項
產生簽名URL過程中,SDK利用本機存放區的密鑰資訊,根據特定演算法計算出簽名(signature),然後將其附加到URL上,以確保URL的有效性和安全性。這一系列計算和構造URL的操作都是在用戶端完成,不涉及網路請求到服務端。因此,產生簽名URL時不需要授予調用者特定許可權。但是,為避免第三方使用者無法對簽名URL授權的資源執行相關操作,需要確保調用產生簽名URL介面的身份主體被授予對應的許可權。
例如,通過簽名URL上傳檔案時,需要授予oss:PutObject許可權。通過簽名URL下載或預覽檔案時,需要授予oss:GetObject許可權。
通過以下樣本產生的簽名URL中如果包含特殊符號
+
,可能出現無法正常訪問該簽名URL的現象。如需正常訪問該簽名URL,請將簽名URL中的+
替換為%2B
。
以下是使用簽名URL臨時授權的常見樣本。