1、注册阿里云并开通OSS服务
略😛
2、采用WEB端直接上传至OSS的方式上传文件
2-1、采用STS临时授权的方式让WEB端直接访问OSS
1.某些用户可能需要直接访问OSS资源。
2.对于这部分用户,只需要生成一个临时访问凭证(通过阿里云STS服务为阿里云账号(或RAM用户)提供临时访问权限管理。)给用户使用即可,不需要关心权限撤销问题,临时访问凭证过期后会自动失效。
4.通过STS生成的临时访问凭证包括 安全令牌 (SecurityToken) STS AK(AccessKeyId和AccessKeySecret)
5.使用AccessKey方法与您在使用阿里云账户或RAM用户AccessKey发送请求时的方法相同。需要注意的是在每个向OSS发送的请求中必须携带安全令牌。
更详细的介绍:阿里云User
2-2、配置OSS存储桶
创建一个名为blog-userdata的Bucket用于存储用户数据;
进入Bucket -> 权限管理-跨域设置
配置为
来源:设置为*。
允许 Methods:选中GET、POST、PUT、DELETE以及HEAD。
允许 Headers:设置为*。
暴露 Headers:设置为ETag、x-oss-request-id和x-oss-version-id。
2-3、配置RAM访问控制
1、创建阿里云子账号。
云账号登录RAM控制台。 在左侧导航栏的人员管理菜单下,单击用户。 单击新建用户。
- 输入登录名称和显示名称。
- 在访问方式区域下,选择编程访问。
- 单击确定,然后单击复制保存访问密钥(AccessKeyId 和 AccessKeySecret)。
- 选中创建的子账号,单击添加权限。
- 在添加权限页面,为已创建的子账号添加AliyunSTSAssumeRoleAccess权限。
- 单击确定。
2、创建权限策略。
在左侧导航栏的权限管理菜单下,单击权限策略管理。
单击新建权限策略。
填写策略名称和备注。
配置模式选择脚本配置 为ossUsers添加ListObjects、PutObject、GetObject等权限,在策略内容中配置脚本示例如下:
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": [ "oss:ListObjects", "oss:PutObject", "oss:AbortMultipartUpload", "oss:GetObject" ], "Resource": [ "acs:oss:*:*:blog-userdata", "acs:oss:*:*:blog-userdata/*" ] } ] }
3.创建角色并记分配权限策略
- 在左侧导航栏,单击RAM角色管理。
- 单击新建RAM角色,选择可信实体类型为阿里云账号,单击下一步。
- 在新建RAM角色页面,填写RAM角色名称和备注。
- 选择云账号为当前云账号。
- 单击完成,之后单击为角色授权。
- 在添加权限页面,选择自定义权限策略,添加步骤2中创建的权限策略。
- 获取这个角色的ARN 例如
acs:ram::13**********623:role/ramosstest
到此为止 我们 创建了一个阿里云子账户、创建了OSS(blog-userdata)的权限策略、创建了一个角色并分配了OSS(blog-userdata)的权限策略、获取了这个角色的ARN。
此步骤不明白的建议仔细阅读官方文档,多实践几遍😄
3、Eggjs 服务端接口实现
3-1、搭建Eggjs项目
略😛
不会的可以看我上一篇 用Eggjs 实现 RESTful API
3-2、实现TST授权接口
1.安装依赖 npm install @alicloud/sts-sdk
2.配置config参数
// ./config/config.default.js
// STS - OSS
config.sts = {
endpoint: 'sts.aliyuncs.com', // 在中国内地,您可以直接使用该统一公网接入地址,也可以使用所在地域的接入地址。
accessKeyId: 'LT************RVns', // check this from aliyun console
accessKeySecret: 'oPe*************4Wn', // check this from aliyun console
};
3.配置路由
// ./app/.router.js
// Cloud
router.get('/api/v1/ossToken', app.jwt, controller.cloud.getStsToken);
4.controller
// ./app/controller/cloud.js
'use strict';
const Controller = require('egg').Controller;
const getTokenRule = {
accountID: { type: 'string', required: true },
roleName: { type: 'string', required: true },
};
class CloudController extends Controller {
async getStsToken() {
const { ctx } = this;
ctx.validate(getTokenRule, ctx.query);
// 处理逻辑
const { code, body } = await ctx.service.cloud.getStsToken(ctx.query);
// 返回响应体和状态码
ctx.body = { ...body };
ctx.status = code;
}
}
module.exports = CloudController;
5.service
// ./app/service/cloud.js
'use strict';
const Service = require('egg').Service;
const StsClient = require('@alicloud/sts-sdk');
class CloudService extends Service {
async getStsToken(query) {
const { accountID, roleName } = query;
const {
endpoint,
accessKeyId,
accessKeySecret,
} = this.config.sts;
const sts = new StsClient({
endpoint,
accessKeyId,
accessKeySecret,
});
/**
* assumeRole(RoleArn,RoleSessionName)
* RoleArn:指定角色的ARN。格式:acs:ram::$accountID:role/$roleName 。
* RoleSessionName: 用户自定义参数。此参数用来区分不同的令牌,可用于用户级别的访问审计。
*/
const res1 = await sts.assumeRole(
`acs:ram::${accountID}:role/${roleName}`,
'client_web'
);
console.log(res1);
if (res1.Credentials.SecurityToken) {
const res2 = await sts.getCallerIdentity();
console.log(res2);
return { code: 200, body: { status: true, msg: '获取成功', data: res1 } };
}
return { code: 500, body: { status: true, msg: '获取失败' } };
}
}
module.exports = CloudService;
6.访问接口测试
$ curl --location --request GET 'http://localhost:7001/api/v1/ossToken?accountID=1332314452386623&roleName=ramosstest' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZmMzNWI4YjZiYmI2ODMzNmU3NTEyYjgiLCJuYW1lIjoi55So5oi3NzE5NzM1Iiwic3RhdHVzIjoxMDAsImlhdCI6MTYwNjcyNDk1NCwiZXhwIjoxNjA2ODExMzU0fQ.5pxEeb39H8_RDyclMraKxSW4hSrFw6333f-qeCBuFYw'
// 返回 *为省略
{
"status": true,
"msg": "获取成功",
"data": {
"SecurityToken": "CAIS8wF1q6Ft5B2yfSjIr**********dQMEUzFOG4Pw==",
"AccessKeyId": "STS.NT7np***********36sLUaER",
"AccessKeySecret": "C5rBieF**********4JnAm6rVYnvppEFqezw",
"Expiration": "2020-11-31T04:53:23Z"
}
}
4、Web端 Vue上传文件实现
1.安装依赖
npm install ali-oss --save
2.简单的demo
<template>
<div>
<button @click="getOssToken">获取token</button>
<span>OSS 文件上传</span>
<br />
<input ref="file" type="file" id="uploadImage" @change="toUpload" />
<br />
上传后返回URl地址为:{{ imgUrl }}
<img :src="imgUrl" />
</div>
</template>
<script>
import OSS from 'ali-oss'
export default {
data() {
return {
imgUrl: '',
ossConfig: {
accountID: '1332314452386623',
roleName: 'ramosstest'
},
ossParameter: {}
}
},
methods: {
getOssToken() {
this.axios
.get('/api/v1/ossToken', {
params: this.ossConfig
})
.then(res => {
this.ossParameter = res.data.data
console.log(this.ossParameter)
})
},
toUpload() {
console.log('准备上传')
const files = this.$refs.file.files[0]
const name = files.name
console.log(files)
const client = new OSS({
region: 'oss-cn-hangzhou',
accessKeyId: this.ossParameter.AccessKeyId,
accessKeySecret: this.ossParameter.AccessKeySecret,
bucket: 'blog-userdata',
stsToken: this.ossParameter.SecurityToken
})
console.log('初始化完成')
const that = this
client
.multipartUpload(name, files)
.then(function(res) {
const str = res.res.requestUrls[0]
that.imgUrl = str.split('?')[0]
console.log('上传成功!', str.split('?')[0])
})
.catch(err => {
console.log(err)
})
}
}
}
</script>
3.效果预览
返回上传地址为:blog-userdata.oss-cn-hangzhou.aliyuncs.com/xinxiaomeng…
总结
⚠️ 代码不够严谨,请勿copy上生产!
新手容易错在参数的配置,请一定仔细阅读官方文档。