STS临时受权访问OSS你会用了吗

前言

最近在作跟oss上传相关的一些东西,一开始方案是前端直接上传,oss的key,secret都由前端本身配置。 可是这样会存在一些安全问题,若是这个帐号的帐密被泄露了,权限没有作控制的话。不法分子就能够对咱们的 oss上的文件进行各类操做,删除啊,下载之类的。既然有这种安全问题,我们确定是要解决的。通过查看官方 文档知道,阿里云oss支持使用临时token的方式,前端或者说上传者只要拿到了这个token就能够行使响应的权利, 并且这个token是有对应的权限能够控制的,而且由于是临时的嘛,是有过时时间的。即便泄露了呢,我们权限的控制 也能够作到,他只能上传,不能进行其余操做,居然有这么方便的操做?那我们接下来看看吧。html

不重要的闲扯

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

旁白:混博客,涨人气?java

我:额,不是。由于我在看完官方文档后头有点大,文档很丰富,并且有些demo的代码运行以后并无跑起来。根据web端,移动端还区分了好些内容, 真的是要研究一番才看明白STS究竟是怎么一回事,怎么使用。因此特地专门就写STS这一个点,让以后须要使用这个功能的开发朋友们有个比较清晰的理解。就不用 看那么就的文档。git

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

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

STS的流程

oss文档中STS的流程: 安全

STS(Security Token Service)进行临时受权访问。经过STS,您能够为第三方应用或子用户(即用户身份由您本身管理的用户)颁发一个自定义时效和权限的访问凭证。 首先假设读者没有看过oss的文档,只知道有临时token这么个东西。oss那边配置token其实还挺麻烦,首先会涉及到三个东东bash

用户: 通常会建立一个子帐户来充当用户,由于主帐户权限太大。并且假如说是一堆人一块儿使用同一个帐号也很不方便,用着用着别人就把你挤下来了服务器

权限: 对于用户或者角色,他能够进行什么操做。对于oss来讲就是上传文件,删除文件,读取文件这些,oss有专门的命名相似这样:oss:PutObject(这就表明的是上传文件的权限) 若是你想看具体有哪些权限,或者怎么配置能够参考 :基于RAM Policy的权限控制的连接this

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的代码地址,包含了获取token和上传文件的代码,一条龙能够获取token后验证token是否真的生效了:项目地址

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

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

相关文章
相关标签/搜索