鉴于对项目的安全着想,取消用STS鉴权模式(访问密钥(AccessKey ID和AccessKey Secret)要写到项目里)转用自签名模式上传文件,感觉要比平时上传文件(以上传图片参考)返回的更快更便捷一点,也不用亚索之类的,但官方文档上具体示例不是很详细,具体开发过程中也是根据后端来定具体方案的(苦的是我们),下面的示例也仅供参考;
这是官方文档:
您可以把AccessKey ID和AccessKey Secret保存在自有服务器中后,通过自有服务器对客户端信息进行签名。具体步骤如下:
-
在客户端获取并发送待签名的字符串到自有服务器。
-
构造请求时通过SDK中OSSCustomSignerCredentialProvider的signContent方法获取待签名的字符串。
-
发送待签名的字符串到自有服务器。
-
-
在自有服务器进行签名并返回签名后的字符串到客户端。
-
按照OSS规定的签名算法对待签名字符串进行签名。关于签名算法的更多信息,请参见在Header中包含签名。
签名算法的格式为
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服务器进行鉴权。
-
至此结束,当然猛的一看觉得很简单的,真正和自己项目上用的话又是另一说了,一开始上面的signContent(String content)里的content是什么都不知道,可是结合自己后端接口后明白了,具体就是
请求入参,注意里面的时间类型获取要按照官方github里的OSSHeaderSignUrl.java这个类参考,(别问为啥当时我也是没注意卡在这个时间格式上),官方的github代码里写的是STS鉴权模式的,不过也情有可原,自签名模式下后端提供的都不一样无法做到一致或一个标准,下面就自己项目里的举例说一下最重要的地方,如果是自有服务器接口请求返回签名,即签名="OSS " + AccessKeyId + ":" + base64(hmac-sha1(AccessKeySecret, content))格式,如下代码参考
OSSCredentialProvider credentialProvider = new OSSCustomSignerCredentialProvider() {
@Override
public String signContent(String content) {
//具体代码不在这里展示,例如接口地址http://localhost:8080/getSign
//这里一定要走同步请求(千万不要异步获取)返回的signature,return出去
return signature;
}
};
OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);
//填写bucketName,objectKey和uploadfilePath
PutObjectRequest put = new PutObjectRequest(bucketName, objectKey, uploadfilePath);
//上传获取结果
PutObjectResult result = oss.putObject(put);
//result.getStatusCode()返回code判断
//获取上传成功后可访问的url
String backUrl = oss.presignPublicObjectURL(bucketName, objectKey);