阿里云对象存储应用服务器搭建代码

背景说明

最近做一个APP客户端图片直传阿里云OSS的服务,需要在后台开一个阿里云的OSSToken获取的接口。

阿里云官方文档地址:快速搭建移动应用直传服务

略过移动端说明,直接看服务端的。

不是移动端直传吗,为什么需要服务端呢?原因如下:

Android和iOS应用不能直接存储AccessKey,这样会存在数据泄露的风险。所以应用必须向用户的应用服务器申请一个Token。

这个Token是有时效性的,如果Token的过期时间是30分钟(由应用服务器指定),那么在这30分钟里,该Android/iOS应用可以使用此Token从OSS上传和下载数据, 30分钟后需要重新获取Token。

正确返回的参数 Expiration 为该Token失效的时间。Android SDK会自动判断Token是否失效,如果失效,则自动获取Token。

代码实现

这里有个Java代码示例,可以下载来参考,把功能集成到项目中,没必要为一个接口单独部署一个项目到服务器。

项目环境是 SpringBoot2.0,JDK8(虽然官方说的是适用java1.7,但是JDK8兼容可用。)

添加依赖

首先在pom中添加相关依赖

        <!--阿里云对象存储-->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-sts</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.0.0</version>
        </dependency>    

配置属性文件

可以从下载的 AppTokenServerDemo 项目中找到 config.json 文件,将其中的五个参数都配置到我们自己的属性文件 application.properties 中。

#阿里云对象存储
ali.oss.AccessKeyID=xxxxxx
ali.oss.AccessKeySecret=xxxxxxxxxxxxxxx
ali.oss.RoleArn=xxxxxxxxxxxxxx
ali.oss.TokenExpireTime=900
ali.oss.PolicyFile=policy/all_policy.txt

编写接口类

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * @date 2019/4/7 20:18
 * @auther wangbo
 */
@Api(tags = {"OSS接口类"})
@RestController
@RequestMapping("/api/oss")
public class ALiOSSController {
    //只有 RAM用户(子账号)才能调用 AssumeRole 接口
    //阿里云主账号的AccessKeys不能用于发起AssumeRole请求
    //请首先在RAM控制台创建一个RAM用户,并为这个用户创建AccessKeys
    @Value("${ali.oss.AccessKeyID}")
    private String accessKeyId;

    @Value("${ali.oss.AccessKeySecret}")
    private String accessKeySecret;

    //RoleArn 需要在 RAM 控制台上获取
    @Value("${ali.oss.RoleArn}")
    private String roleArn;

    //Token 过期时间,默认 900s
    @Value("${ali.oss.TokenExpireTime}")
    private Long tokenExpireTime;

    //阿里云对象存储例子的 token 权限文件
    //all_policy.txt:指定了该token拥有对该账号下创建Bucket、删除Bucket、上传文件、下载文件、删除文件的权限 。
    //bucket_read_policy.txt:指定了该token拥有该账号下对指定Bucket的读权限。
    //bucket_read_write_policy.txt:指定了该token拥有该账号下对指定Bucket的读写权限。
    @Value("${ali.oss.PolicyFile}")
    private String policyFile;

    //目前只有"cn-hangzhou"这个region可用, 不要使用填写其他region的值
    private static final String REGION_CN_HANGZHOU = "cn-hangzhou";

    //这个是STS版本值
    private static final String STS_API_VERSION = "2015-04-01";

    @ApiOperation(value = "获取APPToken", notes = "获取阿里云对象存储的token")
    @GetMapping("/getAppToken")
    public void getAppToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁
        //但是注意RoleSessionName的长度和规则,不要有空格,只能有‘-‘ ‘_‘ 字母和数字等字符
        //具体规则请参考API文档中的格式要求
        String roleSessionName = "alice-001";
        //此处必须为 HTTPS
        ProtocolType protocolType = ProtocolType.HTTPS;
        //获取文件的字符串
        String policy = ReadJson(policyFile);
        //创建json对象
        JSONObject respMap = new JSONObject();
        try {
            final AssumeRoleResponse stsResponse = assumeRole(accessKeyId, accessKeySecret, roleArn, roleSessionName,
                    policy, protocolType, tokenExpireTime);
            //设置获取阿里云对象存储成功的值
            respMap.put("StatusCode", "200");
            respMap.put("AccessKeyId", stsResponse.getCredentials().getAccessKeyId());
            respMap.put("AccessKeySecret", stsResponse.getCredentials().getAccessKeySecret());
            respMap.put("SecurityToken", stsResponse.getCredentials().getSecurityToken());
            respMap.put("Expiration", stsResponse.getCredentials().getExpiration());
        } catch (ClientException e) {
            //设置获取阿里云对象存储失败的值
            respMap.put("StatusCode", "500");
            respMap.put("ErrorCode", e.getErrCode());
            respMap.put("ErrorMessage", e.getErrMsg());
        }
        //response写回json数据
        response(request, response,respMap.toJSONString());
    }

    protected AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret, String roleArn,
                                                    String roleSessionName, String policy, ProtocolType protocolType, long durationSeconds) throws ClientException{
        try {
            //创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
            IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);

            //创建一个 AssumeRoleRequest 并设置请求参数
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setVersion(STS_API_VERSION);
            request.setMethod(MethodType.POST);
            request.setProtocol(protocolType);

            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy);
            request.setDurationSeconds(durationSeconds);

            //发起请求,并得到response
            final AssumeRoleResponse response = client.getAcsResponse(request);

            return response;
        }catch (ClientException e){
            throw e;
        }
    }

    /**
     * 读取配置文件
     * @param path
     * @return
     */
    public static String ReadJson(String path){
        BufferedReader reader = null;
        //返回值,使用StringBuffer
        StringBuffer data = new StringBuffer();
        try {
            //从给定位置获取文件
            ClassPathResource resource = new ClassPathResource(path);
            InputStream inputStream = resource.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream));
            //每次读取文件的缓存
            String temp = null;
            while((temp = reader.readLine()) != null){
                data.append(temp);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭文件流
            if (reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return data.toString();
    }

    /**
     * 服务器响应结果
     * @param request
     * @param response
     * @param results
     * @throws IOException
     */
    private void response(HttpServletRequest request, HttpServletResponse response, String results) throws IOException {
        String callbackFunName = request.getParameter("callback");
        if (callbackFunName==null || callbackFunName.equalsIgnoreCase(""))
            response.getWriter().println(results);
        else
            response.getWriter().println(callbackFunName + "( "+results+" )");
        response.setStatus(HttpServletResponse.SC_OK);
        response.flushBuffer();
    }
}

此外需要把相关的资源文件(可以在下载的demo项目中获取)引入到resource目录下:

踩坑记录

代码中的文件读取部分在我本地 idea 中运行服务时,可以正常执行。但是将服务打包成可执行jar的包,以jar服务运行服务时报错。

java.io.FileNotFoundException: class path resource [policay/all_policay.txt] cannot be resolved to absolute file path because it does not reside in the file system

原因:打包后Spring无法使用resource.getFile()访问JAR中的路径的文件,必须使用resource.getInputStream()。

我尝试了好几种:

(1)使用demo项目中的方式,本地线上都找不到文件

File file = new File("policay/all_policay.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));

(2)使用ResouceUtils类,线上版本找不到文件

File file = ResourceUtils.getFile("classpath:policay/all_policay.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));

(3)最后改为使用InputStream才解决问题。

ClassPathResource resource = new ClassPathResource("policay/all_policay.txt");InputStream inputStream = resource.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

另外注意,该接口需要定义为GET接口,并且响应值不能自定义的,需要按照demo中的形式进行响应,因为该接口是给阿里云OSS调用的,前端会在相应位置配置该接口地址。

参考博客:

快速上手阿里云对象存储(一)

快速上手阿里云对象存储(二)

快速上手阿里云对象存储(三)

原文地址:https://www.cnblogs.com/wbxk/p/10669659.html

时间: 2024-11-05 16:26:54

阿里云对象存储应用服务器搭建代码的相关文章

阿里云对象存储OSS支持版本管理特性

阿里云对象存储OSS现已经全面支持"对象版本管理"特性.该功能适用于所有的存储类型以及区域.当Bucket启用该特性后,"对象版本管理"功能可以保护和恢复误删除.误覆盖的数据. 对象存储OSS"版本管理"具有如下特点: 提供"应用级"数据保护,可防止文件意外覆盖:当Bucket开启版本管理特性后,该Bucket内对象的每次修改.删除操作,OSS都会生成对应的历史版本.授权的用户可以通过控制台.API.SDK等方式查询.下载以及

WPOSS – WordPress阿里云对象存储OSS插件 网站图片分离加速

我们WordPress课堂在前面有一篇文章中介绍到WPCOS插件,这是针对WordPress程序集合腾讯云COS对象存储进行网站图片分离的插件,包括我们网站目前也有在用.可以降低网站的带宽占用,提高网站的访问速度,当然这个需要我们购买对象存储和流量包,必要的成本还是需要的. 不过有些网友提到自己如果在使用阿里云服务器建站的时候,也想用到类似的插件分离网站的图片或者其他附件文件,那在这里笔者就推荐使用类似的WPOSS插件,基于阿里云对象存储OSS的.功能上有些类似WPCOS,但是稍微设置上有一些不

阿里云轻量应用服务器 搭建配置详解

好久没有更新博客了,说来也是惭愧没有养成记录经验的习惯. 有很多技术开发同学都想拥有自己的服务器用来搭建个人网站,或者展示作品,但是怕租上不会配置或者嫌配置繁琐难下决定. 废话不多说直接进入正题,前两天帮朋友配置一台阿里云的轻量应用服务器(注意不是云服务器ECS但是大同小异). 服务器规格 我配置的是1GB内存1核  20GB SSD系统盘 一年(最低配置算下来打折400多),一般个人建站或者拿来自己练手这个配置足够用了,如果公司用可以选择配置更高的. 1.地域选择 推荐大家选择 华东1(杭州)

阿里云对象存储调用例子

import oss2 ACCESS_KEY_ID = 'LTAIF85FxvOeg3o8' ACCESS_KEY_SECRET = '8cLbVNSv0l4W5kpMkdJZoL5hUqyLKm' BUCKET_NAME = "pyserver" HOST_NAME = 'oss-cn-hangzhou.aliyuncs.com' def upload(file_name, file_path): bucket = oss2.Bucket(oss2.Auth(ACCESS_KEY_I

安卓手把手教你结合阿里云OSS存储实现视频(音频,图片)的上传与下载

首先,明白阿里云OSS是个什么鬼 阿里云对象存储(Object Storage Service,简称OSS),是阿里云对外提供的海量,安全,低成本,高可靠的云存储服务.用户可以通过调用API,在任何应用.任何时间.任何地点上传和下载数据,也可以通过用户Web控制台对数据进行简单的管理.OSS适合存放任意文件类型,适合各种网站.开发企业及开发者使用. 以上是官方解释.可以看出,OSS可以为我们在后台保存任何数据,强大无比. 步入正题: 首先你得有个阿里云账号(淘宝账号也可以哦,毕竟阿里账号都通用)

腾讯云对象存储服务(cos)之PHP实践

云对象存储服务, BAT都有其业务, 本文选择腾讯是因为腾讯有每月免费流量, 而阿里和百度都是需要先付费后使用, 另外新兴的像七牛云存储, 也是很不错的解决方案. 贴代码 <?php /** * Simple Tencent COS SDK * 2016/05/09 * Author: hldh214 <[email protected]> */ // 配置项 start $appid = ''; $bucket_name = ''; $dir_name = ''; $secretID

微信小程序基于腾讯云对象存储的图片上传

在使用腾讯云对象存储之前,公司一直使用的是传统的FTP的上传模式,而随着用户量的不断增加,FTP所暴露出来的问题也越来越多,1.传输效率低,上传速度慢.2.时常有上传其他文件来攻击服务器,安全上得不到保障.所以我们在经过慎重考虑觉得使用第三方的云存储服务. 在最开始的时候我们在腾讯云与阿里云中选择,最终我们选择腾讯云,腾讯云在文件上传用时方面的性能比较突出,文件越大表现越好:在下载用时方面表现略优于阿里云:文件删除用时方面总体速度略逊于,但在不同大小文件删除用时上都比较稳定.当然这与我们主要用于

jeesz分布式架构集成阿里云oss存储

1. 服务接口定义 /** * 文件上传  1:头像 2:显示图片 3:个人封面  :4:基础图片 * @param request * @param response * @param uid 用户id * @param userType 文件上传  1:头像 2:显示图片 3:个人封面  :4:基础图片 0:视频 * @param files 上传的文件对象 * @return * @throws Exception */ @RequestMapping(value = "/upload/b

阿里云轻量应用服务器Linux-Centos7下Oracle19c的安装

初始环境:阿里云轻量应用服务器已经重置系统为CentOS7.3-64位具体目标:安装Oracle Database 19c 第一步:检查Linux系统版本 执行命令 lsb_release -a 查看系统版本可以看到,目前我的系统版本为CentOS7.3-64位.2.为了确保一切正常,我准备升级自己的系统到当前最新.3.用yum更新升级执行命令 yum -y clean all执行命令 yum -y update最后看见"Complete!"就是更新完成了.4.更新完成后,执行命令 l