使用阿里雲OSS的服務端簽名後直傳功能
阿新 • • 發佈:2020-09-16
網站一般都會有上傳功能,而物件儲存服務oss是一個很好的選擇。可以快速的搭建起自己的上傳檔案功能。
該文章以使用阿里雲的OSS功能為例,記錄如何在客戶端使用阿里雲的物件儲存服務。
# 服務端簽名後直傳
## 背景
採用JavaScript客戶端直接簽名(參見JavaScript客戶端簽名直傳)時,AccessKey ID和AcessKey Secret會暴露在前端頁面,因此存在嚴重的安全隱患。因此,OSS提供了服務端簽名後直傳的方案。
## 流程介紹
流程如下圖所示:
![image.png](http://qiniublog.colablog.cn/080c5d0c-c226-4d93-a39a-c76bc52a02b8.png)
本示例中,Web端向服務端請求籤名,然後直接上傳,不會對服務端產生壓力,而且安全可靠。但本示例中的服務端無法實時瞭解使用者上傳了多少檔案,上傳了什麼檔案。如果想實時瞭解使用者上傳了什麼檔案,可以採用服務端簽名直傳並設定上傳回調。
# 建立物件儲存
## 1. 建立bucket
> 快捷入口:[https://oss.console.aliyun.com/bucket](https://oss.console.aliyun.com/bucket)
**bucket讀寫許可權為:公共讀**
## 2. 新增子使用者分配許可權
滑鼠移至右上角的使用者頭像當中,點選 **新增AccessKey管理**, 然後選擇使用子使用者AccessKey,因為使用子使用者可以只分配OSS的讀寫許可權。這樣比較安全。
**訪問方式選擇:程式設計訪問**(即使用AccessKey ID 和 AccessKey Secret, 通過API或開發工具訪問)
然後點選子使用者的新增許可權操作。
**許可權選擇:AliyunOSSFullAccess**(管理物件儲存服務(OSS)許可權)
![image.png](http://qiniublog.colablog.cn/a91eb62a-6223-4a0f-b209-ad3cec118228.png)
## 3.儲存AccessKey資訊
建立了使用者後,會展示這麼一個頁面
![image.png](http://qiniublog.colablog.cn/bb06b199-cf41-48bd-b780-e50e54b5448f.png)
此時你需要**儲存好AccessKeyID和AccessSecret**,否則這個頁面關閉後就找不到了。
# maven依賴
```maven
com.aliyun.oss
aliyun-sdk-oss
3.10.2
```
最新版本可以看這裡:[https://help.aliyun.com/document_detail/32009.html?spm=a2c4g.11186623.6.807.39fb4c07GmTHoV](https://help.aliyun.com/document_detail/32009.html?spm=a2c4g.11186623.6.807.39fb4c07GmTHoV)
# 測試上傳
測試程式碼
```java
// Endpoint以杭州為例,其它Region請按實際情況填寫。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里雲主賬號AccessKey擁有所有API的訪問許可權,風險很高。強烈建議您建立並使用RAM賬號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM賬號。
String accessKeyId = "";
String accessKeySecret = "";
// 建立OSSClient例項。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 建立PutObjectRequest物件。
PutObjectRequest putObjectRequest = new PutObjectRequest("", "test", new File("C:\Users\82131\Desktop\logo.jpg"));
// 上傳檔案。
ossClient.putObject(putObjectRequest);
// 關閉OSSClient。
ossClient.shutdown();
```
![image.png](http://qiniublog.colablog.cn/25c9fbaf-2dc9-468c-bab5-d8dcff072d2e.png)
測試成功後就可以看到test圖片了,如圖:
![image.png](http://qiniublog.colablog.cn/003d7e95-4592-48e1-89a7-f36902162748.png)
# 服務端簽名實現流程
## 修改CORS
客戶端進行表單直傳到OSS時,會從瀏覽器向OSS傳送帶有Origin的請求訊息。OSS對帶有Origin頭的請求訊息會進行跨域規則(CORS)的驗證。因此需要為Bucket設定跨域規則以支援Post方法。
進入bucket後,選擇許可權管理 -》跨域設定 -》建立規則
![image.png](http://qiniublog.colablog.cn/8c6174a3-56ad-4fd0-9037-7940d07667a9.png)
## 後端程式碼
```java
@RestController
public class OssController {
@RequestMapping("/oss/policy")
public Map policy() {
String accessId = ""; // 請填寫您的AccessKeyId。
String accessKey = ""; // 請填寫您的AccessKeySecret。
String endpoint = "oss-cn-shenzhen.aliyuncs.com"; // 請填寫您的 endpoint。
String bucket = "bucket-name"; // 請填寫您的 bucketname 。
String host = "https://" + bucket + "." + endpoint; // host的格式為 bucketname.endpoint
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = format + "/"; // 使用者上傳檔案時指定的字首。
Map respMap = new LinkedHashMap();
// 建立OSSClient例項。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
// PostObject請求最大可支援的檔案大小為5 GB,即CONTENT_LENGTH_RANGE為5*1024*1024*1024。
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
respMap.put("accessid", accessId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return respMap;
}
}
```
更詳細的詳細請檢視這裡:[https://help.aliyun.com/document_detail/91868.html?spm=a2c4g.11186623.2.15.a66e6e28WZXmSg#concept-ahk-rfz-2fb](https://help.aliyun.com/document_detail/91868.html?spm=a2c4g.11186623.2.15.a66e6e28WZXmSg#concept-ahk-rfz-2fb)
## 前端程式碼
以element-ui元件為例,上傳前BeforeUpload先呼叫後端的policy介面獲取簽名信息,然後帶著簽名等資訊和圖片直接上傳到aliyun的OSS。
上傳元件singleUpload.vue,需要改動action的地址:bucket的外網域名(在bucket的概覽裡面可以看到),該檔案是穀粒商城專案的一個上傳元件,我只是copy過來修改了一點點。
```vue
點選上傳
只能上傳jpg/png檔案,且不超過10MB
```
引用SingleUpload元件的頁面的示例程式碼:
```vue
```
# 總結
該文主要由學習穀粒商城專案的實踐過程,技術難度並不大,阿里雲官網有文件可以查閱。
快捷入口:[https://help.aliyun.com/product/31815.html?spm=a2c4g.11186623.6.540.28c66d39lLTogx](https://help.aliyun.com/product/31815.html?spm=a2c4g.11186623.6.540.28c66d39lLTogx)
> 個人部落格網址: https://colablog.cn/
如果我的文章幫助到您,可以關注我的微信公眾號,第一時間分享文章給您
![微信公眾號](http://qiniuyun.colablog.cn/%E4%BA%8C%E7%BB%B4%E7%A0