首先钓辆,作為一個一年多碼農(nóng)經(jīng)驗(yàn)的我徐钠,這是第一次接觸oss瓷产。說起來也挺好不意思的锋边。畢竟上一份工作真的小外包。一些第三方調(diào)用等都已經(jīng)封裝好了的擅笔。而且都是小項目性誉,用到oss也就存存用戶頭像啊羽氮,用戶簡介里的照片啊等等的豁鲤。也不涉及什么需要保密的秽誊。所以大多數(shù)項目都是前端直接調(diào)用oss。壓根不經(jīng)過后端畅形。別管什么安全不安全的养距,起碼簡單方便開發(fā)快是真的诉探。
然后這幾天接觸oss日熬,只能說遇到了一些不能算是坑的坑。在這里吐槽一下肾胯,從老板指示說讓oss在后端授權(quán)前端才能調(diào)用開始竖席,我便開始上網(wǎng)查閱資料【炊牵看了看阿里的文檔毕荐,覺得也沒多么復(fù)雜,所以就沒放在心上艳馒。直到昨天真的打算把這個功能落實(shí)在代碼上了憎亚,于是跟老板問了oss的賬號和密碼。卻不料老板給發(fā)來一個文檔弄慰,其中各種圖片的保存路徑的劃分就不說了第美。最主要的賬號是參數(shù)的形式發(fā)給我的。其中包括AccessKeyID陆爽,AccessKeySecret什往,RoleArn,BucketName慌闭,Endpoint别威,TokenExpireTime躯舔。這五個。好的吧省古,興許人家阿里賬號上有著什么什么重要又私密的東西粥庄,給這些參數(shù)也ok吧。畢竟看官方文檔用到的數(shù)據(jù)也都在了豺妓。
好的飒赃,開始實(shí)踐!我有多信心滿滿最后進(jìn)坑摔得就有多慘科侈。按照阿里官方文檔搭demo载佳。然后我可能也是心大,直接就搭了臨時授權(quán)的demo臀栈。畢竟這也是一年多經(jīng)驗(yàn)帶來的自信蔫慧,覺得一個三方軟件的使用肯定不會做的多難。問題出就出在這了权薯。demo復(fù)制粘貼添添改改刪刪姑躲。。于是跑起來了~~~這里要介紹一些oss的知識:
oss的授權(quán)訪問分為兩種:
使用STS進(jìn)行臨時授權(quán):
STS的優(yōu)勢如下:
您無需透露您的長期密鑰(AccessKey)給第三方應(yīng)用盟蚣,只需生成一個訪問令牌并將令牌交給第三方應(yīng)用黍析。您可以自定義這個令牌的訪問權(quán)限及有效期限。
您無需關(guān)心權(quán)限撤銷問題屎开,訪問令牌過期后自動失效阐枣。
使用簽名URL進(jìn)行臨時授權(quán):
生成簽名URL
您可以將生成的簽名URL提供給訪客進(jìn)行臨時訪問。生成簽名URL時奄抽,您可以指定URL的過期時間蔼两,來限制訪客的訪問時長。
官方文檔寫的很清楚逞度,不過寫的sts再好额划,架不住簽名url授權(quán)看起來比較眼熟,所以我選擇了使用簽名URL進(jìn)行臨時授權(quán)档泽;簽名url臨時授權(quán)是分請求的俊戳。get的url獲取最簡單:
// Endpoint以杭州為例,其它Region請按實(shí)際情況填寫馆匿。
String endpoint ="http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主賬號AccessKey擁有所有API的訪問權(quán)限抑胎,風(fēng)險很高。強(qiáng)烈建議您創(chuàng)建并使用RAM賬號進(jìn)行API訪問或日常運(yùn)維甜熔,請登錄 https://ram.console.aliyun.com 創(chuàng)建RAM賬號圆恤。
String accessKeyId ="<yourAccessKeyId>";//
String accessKeySecret ="<yourAccessKeySecret>";
String bucketName ="<yourBucketName>";
String objectName ="<yourObjectName>";//因?yàn)檫@個我當(dāng)時沒有太看明白,所以特意寫個注釋,萬一有和我一樣傻的呢盆昙。這個是你文件的名字羽历。因?yàn)間et是只能讀取,所以這里就是你想讓訪客讀取的那個文件名淡喜。在put里就是你想保存進(jìn)oss取的名字秕磷。
// 創(chuàng)建OSSClient實(shí)例。
OSSClient ossClient =newOSSClient(endpoint, accessKeyId, accessKeySecret);
// 設(shè)置URL過期時間為1小時炼团。
Date expiration =new Date(new Date().getTime() +3600*1000);
// 生成以GET方法訪問的簽名URL澎嚣,訪客可以直接通過瀏覽器訪問相關(guān)內(nèi)容。
URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
// 關(guān)閉OSSClient瘟芝。ossClient.shutdown();
但是其功能只是讓訪客可以直接通過瀏覽器訪問相關(guān)內(nèi)容易桃。因?yàn)槲覀円獙?shí)現(xiàn)的是前端存圖片,所以這個就pass掉了锌俱。不過只要按照要求配置是沒問題的∥钪#現(xiàn)在的我已經(jīng)做過demo了。一次跑通贸宏。
如果說親們運(yùn)行得到的url有問題的話造寝,可以把錯誤復(fù)制粘貼百度一下。幾乎都能查得到吭练。我記得阿里官方手冊也專門有一個對各種錯誤的解釋的頁面诫龙。
https://error-center.aliyun.com/status/product/Oss
然后繼續(xù)講我遇到的錯誤:
<Code>SignatureDoesNotMatch</Code>
? ? <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
? ? <RequestId>5D16D23D1DE99D87A3686758</RequestId>
? ? <HostId>our-shanghai-cer.oss-cn-shanghai.aliyuncs.com</HostId>
? ? <OSSAccessKeyId>LTAIisi3C6MHfTux</OSSAccessKeyId>
? ? <SignatureProvided>+DaLfan2W/V+ZNJ/bOFECwT0jBY=</SignatureProvided>
? ? <StringToSign>GET
一直報這個錯,百度n次都說讓我檢查簽名和key之類的鲫咽。我也是復(fù)制粘貼手打签赃,因?yàn)榘俣壬虾芏嗾f是不是keyId上有空格啦什么的。但是各種沒用浑侥。問群里大神姊舵,問貼吧大佬晰绎。整整一下午到晚上八點(diǎn)多都在解決這個問題~~知道回家洗完澡還在想能是什么原因寓落。今早上班,在群里大佬的提點(diǎn)下開始懷疑老板給的參數(shù)(一開始是真的沒想到)荞下。于是做了一個最簡單的直傳demo伶选。ok,還是報錯尖昏。而且這次的報錯很明確仰税。
[ErrorCode]: AccessDenied
[RequestId]: 5D1724AA94911CA42A5668FD
[HostId]: our-shanghai-cer.oss-cn-shanghai.aliyuncs.com
[ResponseError]:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
? <Code>AccessDenied</Code>
? <Message>The bucket you access does not belong to you.</Message>
? <RequestId>5D1724AA94911CA42A5668FD</RequestId>
? <HostId>our-shanghai-cer.oss-cn-shanghai.aliyuncs.com</HostId>
</Error>
看到這沒跑了~~就是老板給的參數(shù)是錯了,別管我心理多少頭草泥馬在奔跑了~反正我逝去的一天青春也沒多值錢抽诉。繼續(xù)往下搞的前提問到能用的參數(shù)啊陨簇,所以找老板要參數(shù)。問賬號是多少(因?yàn)槲覀兝习宀⒉皇羌夹g(shù)迹淌,只能說一知半解河绽,所以有點(diǎn)不敢信他的參數(shù)了)己单。結(jié)果過了n久,躊躇的給我發(fā)來了一個賬號和口令耙饰。我猜了一會兒試了一會兒最終登陸成功纹笼,是個阿里云的子賬號。ok吧苟跪,別管我心理舒服不舒服的廷痘,拿著人家工資呢。我自己去建立key然后保存secert件已。這回又搭起了demo笋额。再也不敢一次性做最終目的了。從直傳 開始測試篷扩,而且是一步一測試:
public class Demo {
private static final String ENDPOINT = "oss-cn-shanghai.aliyuncs.com";//根據(jù)你們自己的情況填寫
private static final String ACCESSKEYID = "你的keyId";
private static final String ACCESSKEYSECRET = "你的keySecert";
private static final String BUCKETNAME = "你的bucketName";
public static void main(String[] args) {
OSS ossClient = new OSSClient(ENDPOINT, ACCESSKEYID, ACCESSKEYSECRET);//創(chuàng)建一個oss連接對象
//判斷是否有此工作空間鳞陨,主要是我都對參數(shù)不信任了~~哎~~小心點(diǎn)不會錯
?if (!ossClient.doesBucketExist(BUCKETNAME)) {
System.out.println("沒有這個bucketName");
}else {
? // 上傳內(nèi)容到指定的存儲空間(bucketName)并保存為指定的文件名稱(objectName)。
? ? ? ? String content = "測試不過吃鍵盤";
//因?yàn)槲疫@里就是個demo瞻惋,所以隨便傳的字符串厦滤。別的格式不一樣的。官方手冊很清楚
? ? ? ? ossClient.putObject(BUCKETNAME, "測試1號", new ByteArrayInputStream(content.getBytes()));
? ? ? ? ossClient.shutdown();
}? ? ?}}
然后運(yùn)行后歼狼,我去oss里面查掏导,確實(shí)保存進(jìn)去了,松了一口氣的感覺羽峰√伺兀卡了我差不多一天半差點(diǎn)對自己喪失信心了。這個成功是信心的找回梅屉。然后也說句題外話值纱,有時候確實(shí)會因?yàn)槟涿罘堑脑蚓涂ㄒ欢螘r間。心態(tài)要好坯汤,別煩躁發(fā)怒虐唠,這是正常的。
直傳成功了繼續(xù)研究授權(quán)吧惰聂。因?yàn)樯罡衭rl的坑疆偿。。所以決定還是走大眾路線搓幌。杆故。sts授權(quán)吧。于是開始查sts授權(quán)的demo溉愁〈︻酰看了看官網(wǎng)的demo大體聊一下自己的理解。
sts就是通過oss官方加密生成一個臨時的key和密鑰。然后可以設(shè)置這個臨時密鑰的時間撤蟆。
第一步導(dǎo)包篙贸。sts專屬的兩個:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-sts</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>[4.4.2,5.0.0)</version>
</dependency>
注意下,我們用oss有時候直傳有時候只生成sts臨時密鑰枫疆。所以這個是不同的包的爵川。而且子賬號的授權(quán)也可能不一樣。而oss好多權(quán)限真的很惡心(這里要聲明一點(diǎn)息楔,上文提到的老板給的賬號不對就是這個原因寝贡。他給我的是生成sts的權(quán)限的賬號而我用來直傳和生成url。)值依。只能我我安全意識不夠強(qiáng)吧圃泡。反正我是只覺得麻煩。
言歸正傳愿险。如果想用來直傳需要引入另一個包
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
直傳和生成臨時url上文已經(jīng)講完了這里就不多話了颇蜡。繼續(xù)說怎么生成臨時sts。我直接上代碼:
public ResultBean getSTS() {
try {
// 構(gòu)造 default profile(參數(shù)留空辆亏,無需添加 region ID)
IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
// 用 profile 構(gòu)造 client
DefaultAcsClient client = new DefaultAcsClient(profile);
final AssumeRoleRequest request = new AssumeRoleRequest();
request.setSysEndpoint(endpoint);
request.setSysMethod(MethodType.POST);
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
request.setPolicy(policy); // Optional
final AssumeRoleResponse response = client.getAcsResponse(request);
return Tools.result(200, "獲取sts臨時憑證成功", response, true);
} catch (Exception e) {
LOG.info("Error Message: " + e.getMessage());
return Tools.result(500, "獲取sts臨時憑證失敗", null, false);
}
}
敲黑板說一下幾個參數(shù):
7绯印!扮叨!這里要敲黑板注意g拖摇!彻磁!注意endpoint這個參數(shù)0濉!就是"sts.aliyuncs.com"這個衷蜓。其實(shí)也可以換成別的累提。但是跟你所認(rèn)知的可能不一樣。都是以sts開頭的磁浇。官方文檔有斋陪。如果不愿意寫這個的親們可以自己去官網(wǎng)查你對應(yīng)的。
還要說一點(diǎn)roleSessionName這個參數(shù)扯夭。有的帖子上說可以不寫之類的鳍贾。但是我不知道是版本更新了還是咋的。反正現(xiàn)在的一定要寫的交洗。
?policy 這個參數(shù)是可以自定義。但是因?yàn)槲沂钦罩俜绞謨缘膁emo改的橡淑。所以這個也就沒改~~
protected static final Logger LOG = LoggerFactory.getLogger(OssUtil.class);
private final static String endpoint = "sts.aliyuncs.com";
private final static String accessKeyId = "我的keyId";
private final static String accessKeySecret = "i我的密鑰";
private final static String roleArn = "這個可以在控制臺查到";
private final static String roleSessionName = "這個也可以在控制臺查到";
private final static String policy = "{\n" + "? ? \"Version\": \"1\", \n" + "? ? \"Statement\": [\n" + "? ? ? ? {\n"
+ "? ? ? ? ? ? \"Action\": [\n" + "? ? ? ? ? ? ? ? \"oss:*\"\n" + "? ? ? ? ? ? ], \n"
+ "? ? ? ? ? ? \"Resource\": [\n" + "? ? ? ? ? ? ? ? \"acs:oss:*:*:*\" \n" + "? ? ? ? ? ? ], \n"
+ "? ? ? ? ? ? \"Effect\": \"Allow\"\n" + "? ? ? ? }\n" + "? ? ]\n" + "}";
為啥給分開了呢构拳。因?yàn)槲覄倓偺岬搅藱?quán)限問題。上面哪個只能生成sts臨時憑證。所以因?yàn)槲疫€要直傳置森。所以這是兩個子賬號斗埂。然后填寫上也沒啥特別的。
private final static String endpoint_upload = "oss-cn-shanghai.aliyuncs.com";
private final static String accessKeyId_upload = "我的keyid";
private final static String accessKeySecret_upload = "我的密鑰";
private final static String bucketName_upload = "our-shanghai-cer";
反正用了兩天的時間凫海。oss起碼暫時需要的功能都跑通了~~哎呛凶,不容易啊~~我感覺最大的坑就是各種權(quán)限~~~嘖嘖
好了好了有問題留言,歡迎糾錯~~
喏行贪,手打不易漾稀,大家動動小手分享轉(zhuǎn)發(fā)點(diǎn)贊評論啥的~~~~