快速搭建移動應(yīng)用上傳回調(diào)服務(wù)
本文講解如何搭建一個基于OSS的移動應(yīng)用數(shù)據(jù)直傳服務(wù)并設(shè)置上傳回調(diào)。
背景信息
快速搭建移動應(yīng)用直傳服務(wù)介紹了如何快速搭建一個基于OSS的移動應(yīng)用數(shù)據(jù)直傳服務(wù)。但該方案有個問題:對于Android/iOS移動應(yīng)用來說,只需要申請一次STS憑證,就能多次使用該STS憑證上傳數(shù)據(jù)到OSS。這就導(dǎo)致應(yīng)用服務(wù)器無法得知用戶上傳了哪些數(shù)據(jù) ,作為該App的開發(fā)者,就無法對應(yīng)用上傳數(shù)據(jù)進(jìn)行管理。為此OSS提供了上傳回調(diào)方案。
流程介紹
上傳回調(diào)的開發(fā)流程如下:
OSS在收到Android/iOS移動應(yīng)用的數(shù)據(jù)(上圖中步驟5)和在返回用戶上傳結(jié)果(上圖中步驟7)之間,觸發(fā)一個上傳回調(diào)任務(wù),即第上圖中步驟6,通過回調(diào)用戶服務(wù)器獲取應(yīng)用服務(wù)器返回的內(nèi)容,然后將此內(nèi)容返回給Android/iOS移動應(yīng)用。詳情請參見Callback API文檔。
上傳回調(diào)的作用
通過上傳回調(diào)讓用戶應(yīng)用服務(wù)器知道當(dāng)前上傳文件的基本信息。
返回的基本信息可以包含下表中一個或多個變量,返回內(nèi)容的格式在Android/iOS上傳時指定。
系統(tǒng)變量
含義
bucket
移動應(yīng)用上傳文件到OSS的哪個存儲空間
object
移動應(yīng)用上傳文件到OSS后保存的文件名
etag
該上傳的文件的ETag,即返回給用戶的etag字段
size
上傳文件的大小
mimeType
資源類型
imageInfo.height
圖片高度
imageInfo.width
圖片寬度
imageInfo.format
圖片格式,如JPG、PNG等
通過上傳回調(diào)設(shè)定自定義參數(shù),達(dá)到信息傳遞的目的。
假如您是一個開發(fā)者,您想知道當(dāng)前用戶所使用的App版本、當(dāng)前用戶所在的操作系統(tǒng)版本、用戶的GPS信息、用戶的手機型號。您可以在Android/iOS端上傳文件時,指定以下自定義參數(shù):
x:version:指定App版本
x:system:指定操作系統(tǒng)版本
x:gps:指定GPS信息
x:phone:指定手機型號
Android/iOS移動應(yīng)用上傳文件到OSS時附帶上述參數(shù),然后OSS把這些參數(shù)放到CallbackBody里發(fā)給應(yīng)用服務(wù)器。這樣應(yīng)用服務(wù)器就能收到這些信息,達(dá)到信息傳遞的目的。
上傳回調(diào)對應(yīng)用服務(wù)器的要求
部署一個可以接收POST請求的服務(wù),這個服務(wù)必須有公網(wǎng)地址,例如
http://example.com/callback.php
。您必須給OSS正確的返回,返回格式必須是JSON格式,內(nèi)容自定義。OSS會把應(yīng)用服務(wù)器返回的內(nèi)容再返回給Android/iOS移動應(yīng)用。詳情請參見Callback API文檔。
在移動應(yīng)用端設(shè)置上傳回調(diào)
要讓OSS在接收上傳請求時觸發(fā)上傳回調(diào),移動應(yīng)用在構(gòu)造上傳請求時必須把如下內(nèi)容指定到上傳請求里面:
要回調(diào)到哪個服務(wù)器(callbackUrl),例如
http://example.com/callback.php
,這個地址必須是公網(wǎng)能夠訪問的。上傳回調(diào)給應(yīng)用服務(wù)器的內(nèi)容(callbackBody),可以是上述OSS返回應(yīng)用服務(wù)器系統(tǒng)變量的一個或者多個。
假如您的用戶服務(wù)器上傳回調(diào)地址是http://example.com/callback.php
。您想獲取手機上傳的文件名稱、文件的大小,并且定義了x:phone變量是指手機型號,x:system變量是指操作系統(tǒng)版本。
上傳回調(diào)示例分以下兩種:
iOS指定上傳回調(diào)示例:
OSSPutObjectRequest * request = [OSSPutObjectRequest new]; request.bucketName = @"<bucketName>"; request.objectKey = @"<objectKey>"; request.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"]; // 設(shè)置回調(diào)參數(shù) request.callbackParam = @{ @"callbackUrl": @"http://example.com/callback.php", @"callbackBody": @"filename=${object}&size=${size}&phone=${x:phone}&system=${x:system}" }; // 設(shè)置自定義變量 request.callbackVar = @{ @"x:phone": @"iphone6s", @"x:system": @"ios9.1" };
Android指定上傳回調(diào)示例:
PutObjectRequest put = new PutObjectRequest(testBucket, testObject, uploadFilePath); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("application/octet-stream"); put.setMetadata(metadata); put.setCallbackParam(new HashMap<String, String>() { { put("callbackUrl", "http://example.com/callback.php"); put("callbackBody", "filename=${object}&size=${size}&phone=${x:phone}&system=${x:system}"); } }); put.setCallbackVars(new HashMap<String, String>() { { put("x:phone", "iPhone 6s"); put("x:system", "YunOS5.0"); } });
應(yīng)用服務(wù)器收到的回調(diào)請求
根據(jù)設(shè)定的不同URL和回調(diào)內(nèi)容,應(yīng)用服務(wù)器收到的回調(diào)請求會有所不同,示例如下:
POST /index.html HTTP/1.0
Host: 203.0.113.0
Connection: close
Content-Length: 81
Content-Type: application/x-www-form-urlencoded
User-Agent: ehttp-client/0.0.1
authorization: kKQe**************/kdD1ktNVgbWE**************
x-oss-pub-key-url: aHR0**************
filename=test.txt&size=5&phone=iphone6s&system=ios9.1
更多內(nèi)容請參見Callback API文檔。
應(yīng)用服務(wù)器判斷回調(diào)請求是否來自OSS
如果您的回調(diào)服務(wù)器被人惡意攻擊了,例如惡意回調(diào)您的應(yīng)用服務(wù)器,導(dǎo)致應(yīng)用服務(wù)器收到一些非法的請求,影響正常邏輯,此時您就需要判斷回調(diào)請求是否來自OSS。
判斷的方法主要是根據(jù)OSS給應(yīng)用服務(wù)器返回的頭部內(nèi)容中 x-oss-pub-key-url
和authorization
這兩個參數(shù)進(jìn)行RSA校驗。只有通過RSA校驗才能說明這個請求是來自OSS。本文提供的示例程序有實現(xiàn)的示例供您參考。
應(yīng)用服務(wù)器收到回調(diào)請求后的處理
應(yīng)用服務(wù)器在校驗這個請求是來自OSS后,指定回調(diào)給應(yīng)用服務(wù)器的內(nèi)容格式,如
filename=test.txt&size=5&phone=iphone6s&system=ios9.1
應(yīng)用服務(wù)器就可以根據(jù)OSS的返回內(nèi)容,解析得到自己想要的數(shù)據(jù)。得到這個數(shù)據(jù)后,應(yīng)用服務(wù)器可以把數(shù)據(jù)存放起來,方便后續(xù)管理。
OSS如何處理應(yīng)用服務(wù)器的返回內(nèi)容
有兩種情況:
OSS將回調(diào)請求發(fā)送給應(yīng)用服務(wù)器,但是應(yīng)用服務(wù)器接收失敗或者訪問不通,OSS會返回給Android/iOS移動應(yīng)用203的狀態(tài)碼,但是數(shù)據(jù)已經(jīng)存放到OSS上了。
應(yīng)用服務(wù)器接收到OSS的回調(diào)請求,并且正確返回了,OSS會返回給Android/iOS移動應(yīng)用狀態(tài)碼200,并把應(yīng)用服務(wù)器返回給OSS的內(nèi)容返回給Android/iOS移動應(yīng)用。
示例程序下載
示例程序只是完成了如何檢查應(yīng)用服務(wù)器收到的簽名, 您需要自行增加對應(yīng)用服務(wù)器收到回調(diào)內(nèi)容的格式解析 。
Java
下載地址。
運行方法:解壓后運行java -jar oss-callback-server-demo.jar 9000。9000是運行的端口,可以自己指定。
說明這個JAR例子在Java 1.7運行通過,如果有問題請依據(jù)提供的代碼自行修改。這是一個Maven項目。
PHP
下載地址。
運行方法:將解壓包部署到Apache環(huán)境下,因為PHP本身語言的特點,某些數(shù)據(jù)頭部的獲取會依賴于環(huán)境。請參考例子根據(jù)實際環(huán)境進(jìn)行修改。
Python
下載地址。
運行方法:解壓后直接運行python callback_app_server.py即可,程序自實現(xiàn)了一個簡單的HTTP Server,運行該程序可能需要安裝RSA的依賴。
Ruby版本
下載地址。
運行方法: 運行ruby server.rb。
常見問題
callback地址是否可以篡改成其他地址,由其他服務(wù)器接收回調(diào)并確認(rèn)上傳成功與否?
不可以篡改成其他地址,因為參數(shù)會被簽名被OSS服務(wù)端驗證,而篡改的內(nèi)容無法通過驗證。