最近在作跟oss上傳相關的一些東西,一開始方案是前端直接上傳,oss的key,secret都由前端本身配置。 可是這樣會存在一些安全問題,若是這個帳號的帳密被泄露了,權限沒有作控制的話。不法分子就能夠對咱們的 oss上的文件進行各類操做,刪除啊,下載之類的。既然有這種安全問題,我們確定是要解決的。通過查看官方 文檔知道,阿里雲oss支持使用臨時token的方式,前端或者說上傳者只要拿到了這個token就能夠行使響應的權利, 並且這個token是有對應的權限能夠控制的,而且由於是臨時的嘛,是有過時時間的。即便泄露了呢,我們權限的控制 也能夠作到,他只能上傳,不能進行其餘操做,居然有這麼方便的操做?那我們接下來看看吧。html
我:閒扯幾句別的,其實官方文檔已經比較豐富了,爲啥我還要寫一篇博客呢?前端
旁白:混博客,漲人氣?java
我:額,不是。由於我在看完官方文檔後頭有點大,文檔很豐富,並且有些demo的代碼運行以後並無跑起來。根據web端,移動端還區分了好些內容, 真的是要研究一番纔看明白STS究竟是怎麼一回事,怎麼使用。因此特地專門就寫STS這一個點,讓以後須要使用這個功能的開發朋友們有個比較清晰的理解。就不用 看那麼就的文檔。git
旁白:這麼說來你還作了一點貢獻?github
我: 您說是就是吧 手動狗頭web
oss文檔中STS的流程: 安全
STS(Security Token Service)進行臨時受權訪問。經過STS,您能夠爲第三方應用或子用戶(即用戶身份由您本身管理的用戶)頒發一個自定義時效和權限的訪問憑證。 首先假設讀者沒有看過oss的文檔,只知道有臨時token這麼個東西。oss那邊配置token其實還挺麻煩,首先會涉及到三個東東bash
用戶: 通常會建立一個子帳戶來充當用戶,由於主帳戶權限太大。並且假如說是一堆人一塊兒使用同一個帳號也很不方便,用着用着別人就把你擠下來了服務器
權限: 對於用戶或者角色,他能夠進行什麼操做。對於oss來講就是上傳文件,刪除文件,讀取文件這些,oss有專門的命名相似這樣:oss:PutObject(這就表明的是上傳文件的權限) 若是你想看具體有哪些權限,或者怎麼配置能夠參考 :基於RAM Policy的權限控制的連接this
RAM: 這個是resource access manager,翻譯爲資源訪問管理。我們其實能夠爲角色,角色應該仍是比較好理解吧,就是某個角色會有相應的職能。好比說醫生,是負責治病的。我們這裏好比定義一個putFileRole,, ,它擁有着上傳的權限。
這三者的關係就是:用戶扮演某個角色,角色擁有着某些權限,用戶也有着一些權限 使用token的時候,我們就把用戶的信息(key,secret)和用戶要扮演的角色信息(arn)傳給阿里雲的服務器, 服務器就會返回token。
1.首先,咱們得建立一個用戶,並賦予他STS的權限。旁白:畢竟是要使用token那用戶首先得有使用token的能力
2.而後咱們須要建立權限,這個權限以後會賦予給角色
3.最後咱們要將權限賦給角色
public Map<String, String> getToken() {
String policy = "{\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Action\": [\n" +
" \"oss:PutObject\"\n" +
" ],\n" +
" \"Effect\": \"Allow\",\n" +
" \"Resource\": [\"acs:oss:*:*:bucket-name/*\", \"acs:oss:*:*:bucket-name\"]\n" +
" }\n" +
" ],\n" +
" \"Version\": \"1\"\n" +
" }";
Map<String, String> resultMap = Maps.newHashMap();
try {
// 添加endpoint(直接使用STS endpoint,前兩個參數留空,無需添加region ID)
// DefaultProfile.addEndpoint("", "cn-hangzhou", "Sts", endpoint);
// 構造default profile(參數留空,無需添加region ID)
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
// 用profile構造client
DefaultAcsClient client = new DefaultAcsClient(profile);
final AssumeRoleRequest request = new AssumeRoleRequest();
request.setMethod(MethodType.POST);
request.setRoleArn(ROLE_ARN);
request.setRoleSessionName(SESSION_NAME);
// 若policy爲空,則用戶將得到該角色下全部權限
request.setPolicy(policy);
// 設置憑證有效時間 單位秒 15分鐘到1小時
request.setDurationSeconds(3600L);
final AssumeRoleResponse response = client.getAcsResponse(request);
resultMap.put("expiration", response.getCredentials().getExpiration());
resultMap.put("accessKeyId", response.getCredentials().getAccessKeyId());
resultMap.put("accessKeySecret", response.getCredentials().getAccessKeySecret());
resultMap.put("securityToken", response.getCredentials().getSecurityToken());
} catch (Exception e) {
log.info("上傳異常:", e);
}
return resultMap;
}
複製代碼
圖中大寫下劃線的邊量是類文件中要配置的參數
要注意的點: 1.有一個坑點要注意: 官方文檔中加了endpoint參數
// 添加endpoint(直接使用STS endpoint,前兩個參數留空,無需添加region ID)
DefaultProfile.addEndpoint("", "cn-hangzhou", "Sts", endpoint);
複製代碼
這個我加上以後就報了一個異常
com.aliyuncs.exceptions.ClientException: SDK.ServerUnreachable : Speicified endpoint or uri is not valid.
複製代碼
因此若是你也出現了這個異常,記得去掉endpoint的配置。
2.代碼中policy能夠不要,這樣就獲取到的是角色的全部權限。若是設了policy的話,會取配置的policy權限和角色權限的交集。
3.duration這個要注意的一個點是返回的是UTC的時間,對於我們東八區的觀衆須要加上8小時纔是咱們使用的時間。 而後這個duration返回的是token過時的最終時間。只能設置15分鐘到1小時,單位是秒。
4.使用token的時候若是權限給的不夠,或者配置權限有問題,會出現以下錯誤:
You have no right to access this object because of bucket acl.
複製代碼
這時候記得去檢查下角色權限和配置
5.附上github的代碼地址,包含了獲取token和上傳文件的代碼,一條龍能夠獲取token後驗證token是否真的生效了:項目地址
6.權限可能報錯的異常,能夠從這個文檔中找到相關的解答:問題處理連接
最近弄了個公衆號,求關注哇,更多原創乾貨等着你~