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; } };
自簽名模式
您可以把AccessKey ID和AccessKey Secret儲存在自有伺服器中後,通過自有伺服器對用戶端資訊進行簽名。具體步驟如下:
在用戶端擷取並發送待簽名的字串到自有伺服器。
構造請求時通過SDK中OSSCustomSignerCredentialProvider的signContent方法擷取待簽名的字串。
發送待簽名的字串到自有伺服器。
在自有伺服器進行簽名並返回簽名後的字串到用戶端。
按照OSS規定的簽名演算法對待簽名字串進行簽名。關於簽名演算法的更多資訊,請參見簽名版本1。
簽名演算法的格式為
signature = "OSS " + AccessKeyId + ":" + base64(hmac-sha1(AccessKeySecret, content))
,其中content是已根據請求參數拼接後的字串。返回簽名後的字串給用戶端。
假設服務端地址為http://localhost:8080/sign,將content傳給服務端進行簽名,擷取簽名後的signature返回給用戶端。範例程式碼如下:
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; OSSCredentialProvider credentialProvider = new OSSCustomSignerCredentialProvider() { @Override public String signContent(String content) { URL stsUrl = new URL("http://localhost:8080/sign?content=" + content); HttpURLConnection conn = (HttpURLConnection) stsUrl.openConnection(); InputStream input = conn.getInputStream(); String jsonText = IOUtils.readStreamAsString(input, OSSConstants.DEFAULT_CHARSET_NAME); JSONObject jsonObjs = new JSONObject(jsonText); String signature = jsonObjs.getString("signature"); return signature; } }; OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);
在用戶端發送簽名後的字串到OSS伺服器進行鑒權。
簽名URL
您可以將產生的簽名URL提供給訪客進行臨時訪問。產生簽名URL時,您可以自訂URL的到期時間來限制訪客的訪問時間長度。
通過以下樣本產生的簽名URL中如果包含特殊符號+
,可能出現無法正常訪問該簽名URL的現象。如需正常訪問該簽名URL,請將簽名URL中的+
替換為%2B
。
以下代碼用於產生簽名URL,並通過簽名URL上傳和下載檔案。