阿里云OSS移动应用直传服务

官方文档:

快速搭建移动应用直传服务 权限管理 STS临时授权访问 访问控制 RAM Policy Editor

源码下载:

注:
PHP下载地址解压后的 sts-server/policy/all_policy.txt,本人经过微调,否则直接使用官网下的代码,会一直报“AccessDeny”错误。若使用bucket_read_policy.txt或者bucket_read_write_policy.txt,请将 “$BUCKET_NAME”替换为您的bucket名称。自定义的策略也可以自行编辑,或通过RAM Policy Editor编写。之后替换config.json 内的PolicyFile字段值即可。

STS配置及内容说明

认真看完权限管理篇章,对权限、子账号、bucket、STS临时授权有比较全面详细的了解了。

使用快速搭建移动应用直传服务,阿里云会自动生成并配置以下几项:

  • 用户(AliyunOSSTokenGeneratorUser)

  • 策略(AliyunOSSTokenGeneratorRolePolicy,AliyunOSSTokenGeneratorUserPolicy)

  • 角色(AliyunOSSTokenGeneratorRole)

这些配置也可通过STS临时授权访问自己创建并配置。

用户(AliyunOSSTokenGeneratorUser)为子账号,至于为何要用子账号,请查阅不使用主账号。主要还是权限及安全因素。

AliyunOSSTokenGeneratorUser、 AliyunOSSTokenGeneratorRolePolicy、AliyunOSSTokenGeneratorUserPolicy、 AliyunOSSTokenGeneratorRole 之间的关系及主要代码如下图所示:

OSS-STS授权配置

创建及授权流程如下所示:

STS配置创建流程

aliyun管理控制台配置1、2两大步,第3步 Token AK创建由应用服务器调用sdk创建。

应用服务器端配置

应用服务器端的配置除了上面“注”中提到的,就是配置config.json中的7个参数

1
2
3
4
5
6
7
8
9
{
"AccessKeyID" : "",
"AccessKeySecret" : "",
"RoleArn" : "",
"BucketName" : "",
"Endpoint" : "",
"TokenExpireTime" : "900",
"PolicyFile": "policy/all_policy.txt"
}

说明:

  1. AccessKeyID:填写上述图标红的参数1的内容。
  2. AccessKeySecret:填写上述图标红的参数2的内容。
  3. RoleArn:填写上述图标红的参数3的内容。
  4. BucketName:填写需要操作的bucket名称,默认值可以不修改
  5. Endpoint:填写您的阿里云OSS服务的访问域名, 默认值可以不修改。(用户自定义域名没试过)
  6. TokenExpireTime:指Android/iOS应用取到这个Token的失效时间,注意,最少是900s,默认值可以不修改。
  7. PolicyFile:填写的是该Token所要拥有的权限列表的文件, 默认值可以不修改。

将sts-server代码发布后,调用sts.php返回的正确结果为:

1
2
3
4
5
6
7
{
StatusCode: 200,
AccessKeyId: "STS.DW3ffRHD3NPNgv1qFU6ZRk7xQ",
AccessKeySecret: "ZPEKVfqdbcp3oVe5sDztKCwv6gmvZk32Rhqi9dsVgyP",
Expiration: "2018-02-02T13:38:22Z",
SecurityToken: "CAIS+wJ1q6Ft5B2yfSjIpZSGLdzmpZsS+ZKlZVCAlUYAOtV+hPLTszz2IHBNeXNhAuAXsvs3mWFW5/wYlqJ4T55IQ1Dza8J148yMOZ58ns6T1fau5Jko1bdycAr6Umwqta2/SuH9S8ynkJ7PD3nPii50x5bjaDymRCbLGJaViJlhHNZ1Ow6jdmhpCctxLAlvo9N4UHzKLqSVLwLNiGjdB1YKwg1nkjFT5KCy3sC74BjTh0GYr+gOvNbVI4O4V8B2IIwdI9Cux75ffK3bzAtN7wRL7K5skJFc/TDOsrP6BEJKsTGHKPbz+N9iJxNiHOtYfZRJt//hj/Z1l/XOnoDssXZ3MPpSTj7USfLHoq7NE/j7Mc0iJ/SpeSaP8KjWa8Gr6FJ4OC9DZVsRJIB8EBIqV0xwEAO9A7S85VXHbj2kT6W4y6ws2fJ3tQ64pIfQdgPfEunGiXtJZM5mNVlbPhoXzHHndbQdbwtPflVoCrCYV4xvawpErqflrcgFuIfjZ889GoABa/Tnm7uQ+F/Pos+R0sBs/PN+APE4UGHDEJNqXY5ljWTl11l8Wp93FHxBB4CcsarLQ3fvOmIUXqHKLK7me8zOAVZE1/p4jLrR8zyaxFYeDTyWqqur3Ne7im4hSz0B8pYxN3Xw+eKPR6mJ+fsGxtmoQDsU+YHrRmpmtWPWOC28mhY="
}

错误返回格式为:

1
2
3
4
5
{
"StatusCode":500,
"ErrorCode":"InvalidAccessKeyId.NotFound",
"ErrorMessage":"Specified access key is not found."
}

移动端配置

移动端的配置以Android 端为例,iOS端请自行查阅快速搭建移动应用直传服务

初始化OSS endpoint为 “应用服务器端配置”中提到的“您的阿里云OSS服务的访问域名”,比如我的是“oss-cn-shanghai.aliyuncs.com”,可在阿里云管理控制台->对象存储OSS中查看。

1
2
3
4
5
6
7
8
9
10
11
12
private void initOSS(Context context, String endpoint) {
ClientConfiguration conf = new ClientConfiguration();
conf.setConnectionTimeout(15 * 1000); // 连接超时,默认15秒
conf.setSocketTimeout(15 * 1000); // socket超时,默认15秒
conf.setMaxConcurrentRequest(5); // 最大并发请求书,默认5个
conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次

OSSCredentialProvider credentialProvider = new STSGetter();

oss = new OSSClient(context, endpoint, credentialProvider, conf);
OssUploadUtil.oss = oss;
}

其中主要的是STSGetter。STSGetter代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* <pre>
* author : Haitao
* e-mail : haitao_ni@foxmail.com
* time : 2018/2/1
* desc : 重载OSSFederationCredentialProvider生成自己的获取STS的功能
* version: 2.0
* </pre>
*/
public class STSGetter extends OSSFederationCredentialProvider {

private String stsServer;

public STSGetter() {
stsServer = HttpInterface.UserV2.URL_IMAGE_STS;
}

public STSGetter(String stsServer) {
this.stsServer = stsServer;
}

@Override
public OSSFederationToken getFederationToken() {

String stsJson;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(stsServer).build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
stsJson = response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
} catch (IOException e) {
e.printStackTrace();
Log.e("GetSTSTokenFail", e.toString());
return null;
}

try {
JSONObject jsonObjs = new JSONObject(stsJson);
String ak = jsonObjs.getString("AccessKeyId");
String sk = jsonObjs.getString("AccessKeySecret");
String token = jsonObjs.getString("SecurityToken");
String expiration = jsonObjs.getString("Expiration");
return new OSSFederationToken(ak, sk, token, expiration);
} catch (JSONException e) {
Log.e("GetSTSTokenFail", e.toString());
e.printStackTrace();
return null;
}
}

}

之后OSS的操作就可以直接调用OSS提供的SDK内的方法了。

当需要上传文件时,oss会自动调用getFederationToken方法获取授权。当授权过期时,也会oss也会主动重新获取授权,不用开发者操心。

坚持原创技术分享,您的支持是对我最大的鼓励!