STS临时授权访问OSS你知道了吗

前言

最近在做跟oss上传相关的一些东西,一开始方案是前端直接上传,oss的key,secret都由前端自己配置。但是这样会存在一些安全问题,如果这个账号的账密被泄露了,权限没有做控制的话。不法分子就可以对我们的
oss上的文件进行各种操作,删除啊,下载之类的。

既然有这种安全问题,咱们肯定是要解决的。经过查看官方文档知道,阿里云oss支持使用临时token的方式,前端或者说上传者只要拿到了这个token就可以行使响应的权利,而且这个token是有对应的权限可以控制的,并且因为是临时的嘛,是有过期时间的。即使泄露了呢,咱们权限的控制也可以做到,他只能上传,不能进行其他操作,竟然有这么方便的操作?那咱们接下来看看吧。

不重要的闲扯

我:闲扯几句别的,其实官方文档已经比较丰富了,为啥我还要写一篇博客呢?

旁白:混博客,涨人气?

我:额,不是。因为我在看完官方文档后头有点大,文档很丰富,而且有些demo的代码运行之后并没有跑起来。根据web端,移动端还区分了好些内容,真的是要研究一番才看明白STS到底是怎么一回事,怎么使用。所以特意专门就写STS这一个点,让之后需要使用这个功能的开发朋友们有个比较清晰的理解。就不用看那么久的文档,花那么多时间理解。

旁白:这么说来你还做了一点贡献?

我: 您说是就是吧 手动狗头

STS的流程

oss文档中STS的流程:

STS(Security Token Service)进行临时授权访问。通过STS,您可以为第三方应用或子用户(即用户身份由您自己管理的用户)颁发一个自定义时效和权限的访问凭证。

首先假设读者没有看过oss的文档,只知道有临时token这么个东西。oss那边配置token其实还挺麻烦,首先会涉及到三个东东

用户:
一般会创建一个子账户来充当用户,因为主账户权限太大。而且假如说是一堆人一起使用同一个账号也很不方便,用着用着别人就把你挤下来了

权限:
对于用户或者角色,他可以进行什么操作。对于oss来说就是上传文件,删除文件,读取文件这些,oss有专门的命名类似这样:oss:PutObject(这就代表的是上传文件的权限)如果你想看具体有哪些权限,或者怎么配置可以参考 :基于RAM Policy的权限控制的链接

RAM:
这个是resource access manager,翻译为资源访问管理。咱们其实可以为角色,角色应该还是比较好理解吧,就是某个角色会有相应的职能。比如说医生,是负责治病的。咱们这里比如定义一个putFileRole,它拥有着上传的权限。

这三者的关系就是:用户扮演某个角色,角色拥有着某些权限,用户也有着一些权限,使用token的时候,咱们就把用户的信息(key,secret)和用户要扮演的角色信息(arn)传给阿里云的服务器,服务器就会返回token。

具体操作流程

1.首先,我们得创建一个用户,并赋予他STS的权限。
旁白:毕竟是要使用token那用户首先得有使用token的能力

2.然后我们需要创建权限,这个权限之后会赋予给角色

3.最后我们要将权限赋给角色

public Map<String, String> getToken() {
    
    
       String policy = "{\n" +
               "    \"Statement\": [\n" +
               "      {\n" +
               "        \"Action\": [\n" +
               "          \"oss:PutObject\"\n" +
               "        ],\n" +
               "        \"Effect\": \"Allow\",\n" +
               "        \"Resource\": [\"acs:oss:*:*:bucket-name/*\", \"acs:oss:*:*:bucket-name\"]\n" +
               "      }\n" +
               "    ],\n" +
               "    \"Version\": \"1\"\n" +
               "  }";
       Map<String, String> resultMap = Maps.newHashMap();
       try {
    
    
           // 添加endpoint(直接使用STS endpoint,前两个参数留空,无需添加region ID)
           // DefaultProfile.addEndpoint("", "cn-hangzhou", "Sts", endpoint);

           // 构造default profile(参数留空,无需添加region ID)
           IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
           // 用profile构造client
           DefaultAcsClient client = new DefaultAcsClient(profile);
           final AssumeRoleRequest request = new AssumeRoleRequest();
           request.setMethod(MethodType.POST);
           request.setRoleArn(ROLE_ARN);
           request.setRoleSessionName(SESSION_NAME);
           // 若policy为空,则用户将获得该角色下所有权限
           request.setPolicy(policy);
           // 设置凭证有效时间 单位秒  15分钟到1小时
           request.setDurationSeconds(3600L);

           final AssumeRoleResponse response = client.getAcsResponse(request);
           resultMap.put("expiration", response.getCredentials().getExpiration());
           resultMap.put("accessKeyId", response.getCredentials().getAccessKeyId());
           resultMap.put("accessKeySecret", response.getCredentials().getAccessKeySecret());
           resultMap.put("securityToken", response.getCredentials().getSecurityToken());
       } catch (Exception e) {
    
    
           log.info("上传异常:", e);
       }
       return resultMap;
   }

图中大写下划线的边量是类文件中要配置的参数

要注意的点:
1.有一个坑点要注意:官方文档中加了endpoint参数

// 添加endpoint(直接使用STS endpoint,前两个参数留空,无需添加region ID)
DefaultProfile.addEndpoint("", "cn-hangzhou", "Sts", endpoint);

这个我加上之后就报了一个异常

com.aliyuncs.exceptions.ClientException: SDK.ServerUnreachable : Speicified endpoint or uri is not valid.

所以如果你也出现了这个异常,记得去掉endpoint的配置。

2.代码中policy可以不要,这样就获取到的是角色的所有权限。如果设了policy的话,会取配置的policy权限和角色权限的交集。

3.duration这个要注意的一个点是返回的是UTC的时间,对于咱们东八区的观众需要加上8小时才是我们使用的时间。然后这个duration返回的是token过期的最终时间。只能设置15分钟到1小时,单位是秒。

4.使用token的时候如果权限给的不够,或者配置权限有问题
会出现如下错误:

You have no right to access this object because of bucket acl.

这时候记得去检查下角色权限和配置

5.附上github的代码地址:项目地址

6.权限可能报错的异常,可以从这个文档中找到相关的解答:问题处理链接

最近弄了个公众号,求关注哇,更多原创干货等着你~

猜你喜欢

转载自blog.csdn.net/sc9018181134/article/details/104351247