上传阿里云OSS最佳实践方案(web直传)

OSS简介

阿里云对象存储OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,可提供99.9999999999%(12个9)的数据持久性,99.995%的数据可用性。多种存储类型供选择,全面优化存储成本。可以通过阿里云提供的简单的REST接口,在任何时间、任何地点、任何互联网设备上进行上传和下载数据。基于OSS,可以搭建出各种多媒体分享网站、网盘、个人和企业数据备份等基于大规模数据的服务。

sts介绍

阿里云STS(Security Token Service)是阿里云提供的一种临时访问权限管理服务。RAM提供RAM用户和RAM角色两种身份。其中,RAM角色不具备永久身份凭证,而只能通过STS获取可以自定义时效和访问权限的临时身份凭证,即安全令牌(STS Token)。

STS的优势:

  • 使用STS Token,减少长期访问密钥(Accesskey)泄露的风险。
  • STS Token具有时效性,可以自定义有效期,到期后将自动失效,无需定期轮换。
  • 可以为STS Token绑定自定义权限策略,提供更加灵活和精细的云资源授权。

逻辑框图

图片[1]-上传阿里云OSS最佳实践方案(web直传)-睿冰小站

代码实现

以下给出两个Java后端接口,分别是获取STS临时令牌接口与生成图像临时访问链接接口。

封装OSS工具类

public class OssUtil {
    public static Logger logger = LoggerFactory.getLogger(OssUtil.class);
    public static final String ACCESS_KEY_ID = "ACCESS_KEY_ID";
    public static final String ACCESS_KEY_SECRET = "ACCESS_KEY_SECRET";
    public static final String SECURITY_TOKEN = "SECURITY_TOKEN";
    public static final String EXPIRATION = "EXPIRATION";
    //这里使用cn-shanghai区域,具体根据实际情况而定
    private static final String REGION = "cn-shanghai";
    private static final String STS_API_VERSION = "2015-04-01";

    /**
     * 生成临时访问令牌
     * @param userName
     * @param roleArn
     * @param accessKeyId
     * @param accessKeySecret
     * @param bucketName
     * @return
     * @throws ClientException
     */
    public static JSONObject getCredit(String userName, String roleArn, String accessKeyId, String accessKeySecret, String bucketName) throws ClientException {
        // 用于阿里云后台审计使用的临时名称,可根据实际业务传输,具体内容不影响服务使用
        String roleSessionName = userName;
        //运行时的策略权限,这里将权限放到了最大,可根据实际情况而定。在运行时,实际权限为这里设置的权限和第一步中角色配置的策略权限的交集
        JSONObject policyObject = new JSONObject();
        policyObject.fluentPut("Version", "1");
        List<JSONObject> statements = new ArrayList<>();
        statements.add(new JSONObject().fluentPut("Effect", "Allow").fluentPut("Action", Arrays.asList("oss:PutObject")).fluentPut("Resource", Arrays.asList("acs:oss:*:*:" + bucketName, "acs:oss:*:*:" + bucketName + "/*")));
        policyObject.fluentPut("Statement", statements);
        logger.info("ali policy:{}", policyObject);

        //执行角色授权
        IClientProfile profile = DefaultProfile.getProfile(REGION, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);
        final AssumeRoleRequest request = new AssumeRoleRequest();
        request.setVersion(STS_API_VERSION);
        request.setRoleArn(roleArn);
        request.setRoleSessionName(roleSessionName);
//        request.setPolicy(policyObject.toJSONString());
        //临时授权有效实践,从900到3600
        request.setDurationSeconds(900L);
        final AssumeRoleResponse response = client.getAcsResponse(request);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put(ACCESS_KEY_ID, response.getCredentials().getAccessKeyId());
        jsonObject.put(ACCESS_KEY_SECRET, response.getCredentials().getAccessKeySecret());
        jsonObject.put(SECURITY_TOKEN, response.getCredentials().getBizSecurityToken());
        jsonObject.put(EXPIRATION, response.getCredentials().getExpiration());
        return jsonObject;
    }

    /**
     * 生成图片的访问路径
     * @param key
     * @param roleArn
     * @param accessKeyId
     * @param accessKeySecret
     * @param bucketName
     * @return
     */
    public static URL getImgUrl(String key, String roleArn, String accessKeyId, String accessKeySecret, String bucketName){
        OSS client = new OSSClientBuilder().build("oss-cn-shanghai.aliyuncs.com", accessKeyId, accessKeySecret);
        return client.generatePresignedUrl(bucketName, key, new Date(new Date().getTime() + 3600L*1000));
    }
}

获取临时令牌与临时地址

@RestController
@RequestMapping("/oss")
public class OssController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    //属性注入,在yml配置文件中进行配置
    @Value("${oss.region}")
    private String ossRegion;

    @Value("${oss.bucket}")
    private String ossBucket;

    @Value("${oss.accesskey.id}")
    private String ossAccessKeyId;

    @Value("${oss.accesskey.secret}")
    private String ossAccessKeySecret;

    @Value("${oss.role.arn}")
    private String ossRoleArn;

    /**
     * 获取临时授权信息,进行图片上传操作
     *
     * @return
     * @throws ClientException
     */
    @GetMapping("/getCredit")
    public ViewResult getCredit() throws ClientException {
        JSONObject jsonObject = new JSONObject();
        JSONObject creditInfo;
        String basePath = "<基路径>";
        //获取临时令牌
        creditInfo = OssUtil.getCredit("<用户名>", ossRoleArn, ossAccessKeyId, ossAccessKeySecret, ossBucket);
        //组装返回信息
        //文件存放地域
        jsonObject.put("region", ossRegion);
        //临时访问accessKey
        jsonObject.put("accessKeyId", creditInfo.getString(OssUtil.ACCESS_KEY_ID));
        //临时访问accessKeySecret
        jsonObject.put("accessKeySecret", creditInfo.getString(OssUtil.ACCESS_KEY_SECRET));
        //临时访问token
        jsonObject.put("securityToken", creditInfo.getString(OssUtil.SECURITY_TOKEN));
        //临时访问过期时间
        jsonObject.put("expiration", creditInfo.getString(OssUtil.EXPIRATION));
        //bucket名称
        jsonObject.put("bucket", ossBucket);
        //文件的存放基目录
        jsonObject.put("basePath", basePath);
        return ViewResult.success(jsonObject);
    }

    /**
     * 获取图片地址
     * @param key
     * @return
     */
    @GetMapping("/geturl")
    public ViewResult getUrl(@RequestParam String key){
        URL url = OssUtil.getImgUrl(key, ossRoleArn, ossAccessKeyId, ossAccessKeySecret, ossBucket);
        return ViewResult.success(url);
    }
}
© 版权声明
THE END
喜欢就支持以下吧
点赞10 分享