背景说明

最近做一个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调用的,前端会在相应位置配置该接口地址。

参考博客:

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

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

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

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

  1. 阿里云对象存储OSS访问控制

    阿里云对象存储OSS的Android SDK提供了STS鉴权模式和自签名模式来保障移动终端的安全性. OSS可以通过阿里云STS (Security Token Service) 进行临时授权访问.交 ...

  2. 阿里云对象存储OSS与文件存储NAS的区别

    一.简介 应用场景:选择一款存储产品,面向文档数据的存取,不会涉及到数据处理. 产品选型主要从OSS和NAS中选择一款,满足文档存储的需求. 二.NAS优缺点 NAS 是一种采用直接与网络介质相连的特 ...

  3. 阿里云对象存储OSS使用 HTTPS

    一.前言 阿里云对象存储oss本身也是可以用HTTPS直接访问的,但是它本身的地址是http://***.oss-cn-hangzhou.aliyuncs.com这样的,那么如果我们想使用自己的域名, ...

  4. Delphi阿里云对象存储OSS【支持上传文件、下载文件、删除文件、创建目录、删除目录、Bucket操作等】

    作者QQ:(648437169) 点击下载➨Delphi阿里云对象存储OSS             阿里云api文档 [Delphi阿里云对象存储OSS]支持 获取Bucket列表.设置Bucket ...

  5. 阿里云对象存储OSS

    阿里云的产品种类繁多,今天让我们一起来了解下对象存储(Object Storage Service,简称OSS)吧! 什么是对象存储呢? 简单来说,对象存储OSS是阿里云提供的海量.安全和高可靠的云存 ...

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

    阿里云对象存储OSS现已经全面支持“对象版本管理”特性.该功能适用于所有的存储类型以及区域.当Bucket启用该特性后,“对象版本管理”功能可以保护和恢复误删除.误覆盖的数据. 对象存储OSS“版本管 ...

  7. 阿里云对象存储OSS及CDN加速配置

    目录 十大云存储服务商 1. 登陆阿里云官网,开通对象存储服务 OSS 2. 创建存储空间 3. 绑定自定义域名 4. 配置阿里云CDN加速 5. 购买阿里云免费SSL证书 6. 阿里云CDN配置HT ...

  8. java开发之阿里云对象存储OSS和云数据库Memcache的使用

    web开发中标配:aliyun ECS(阿里云服务器),aliyun RDS(阿里云数据库),aliyun OSS(阿里云对象存储),aliyun Memcache(阿里云缓存数据库). 今天就介绍下 ...

  9. 阿里云对象存储OSS————跨域资源共享(CORS)(m3u8 无法加载m3u8:跨域访问被拒绝)

    今天在做视频直播录像的时候,添加一个录制APP的.M3U8文件到OSS的一个test文件中存储,结果是访问不到了: 提示:无法加载m3u8:跨域访问被拒绝!!!!! 项目代码测试地址:https:// ...

随机推荐

  1. Bootstrap-datepicker3官方文档中文翻译---Event/事件(原文链接 http://bootstrap-datepicker.readthedocs.io/en/latest/index.html)

    Events/事件 DatePicker在某些情况下触发一些事件.所有事件都拥有   传递给任何事件处理程序的  事件对象的    附加数据.(译者注:这里英语拗口,汉语也拗口,我用空格给大家断断句) ...

  2. PHP金钱数字转金钱大写

    /* * 数字金额转换成中文大写金额的函数 * String Int $num 要转换的小写数字或小写字符串 * return 大写数字 */ function num_to_rmb($num){ $ ...

  3. Docker 学习9 Docker私有registry

    一.docker registry分类 二.安装docker-hub提供的registry 1.安装 [root@localhost yum.repos.d]# yum install -y dock ...

  4. 咸鱼入门到放弃12--Filter(过滤器)*

    一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...

  5. Python3-Cookbook总结 - 第二章:字符串和文本

    第二章:字符串和文本 几乎所有有用的程序都会涉及到某些文本处理,不管是解析数据还是产生输出. 这一章将重点关注文本的操作处理,比如提取字符串,搜索,替换以及解析等. 大部分的问题都能简单的调用字符串的 ...

  6. vue样式控制的方式

    创建vue对象: 1.样式控制第一种方式: 直接传递一个数组,注意: 这里的 class 需要使用  v-bind 做数据绑定. 2.样式控制第二种方式: 在数组中使用三元表达式 3.样式控制第三种方 ...

  7. 爬虫之正则和xpath

    一.正解解析 常用正则表达式回顾: 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [-] \D : 非数字 \w :数字.字母.下划线.中 ...

  8. java testng框架的windows自动化-自动运行testng程序下篇

    本文旨在让读者简单了解testng的自动运行 接上文https://www.cnblogs.com/xuezhezlr/p/9213456.html,文章大致把testng中比较特殊的两个xml形式说 ...

  9. 处理Python2.7读写文件中的中文乱码问题

    1.设置默认编码 在Python代码中的任何地方出现中文,编译时都会报错,这时可以在代码的首行添加相应说明,明确utf-8编码格式,可以解决一般情况下的中文报错.当然,编程中遇到具体问题还需具体分析啦 ...

  10. 勾勾街——一个专注于免越狱免签名的苹果ios APP打包生成的网站

    自涛舅舅研发的“苹果ios APP自助生成系统”上线以来,每天都有大量的用户注册和生成免越狱app,为什么? 因为我们有明显的技术优势,APP不需要上架appstore, 生成APP又不需要企业签名证 ...