Reason
In the project, I sometimes encounter things such as uploading files. Generally, the back-end provides an interface. Then when we upload, the back-end transfers to the object storage of Ali OSS or other service providers, and then we get url
Save it or return it to the front-end. This method may not be a big problem in business scenarios where the frequency of uploading pictures is not high. However, if your project is of album type or resource provision type, in short, there will be very frequent uploads. In the file scenario, the bandwidth of the server may not be able to handle it, so is there a better solution?
Server-side signature, client-side direct transmission
In fact, cloud service providers such as Ali, Tencent, and other cloud service providers have similar Ali's 16198f161a54bb STS (Security Token Service) temporary access management service . This time I will take Alibaba Cloud as an example to show you how to use STS Token
. STS token
is signed on the server side, and then provided to the front end, so that the front end can directly use this Token
to directly transfer files to Alibaba Cloud
Sign the server and get the STS token
Here we directly take Node.js
as an example. Services in other languages can be found in the Cloud SDK reference (STS) document . There is Python、Java...
First, we need to install a sts-sdk npm package: @alicloud/sts-sdk
(Nodejs version >= 8.5.0)
npm install @alicloud/sts-sdk
Then we create a new file oss-sts-server.js
in utils, which is used to generate STS Token
for the front-end use (here only as an example, you can package it yourself in the future)
const StsClient = require('@alicloud/sts-sdk');
/**
* 生成STStoken
* @param accessKeyId AccessKey ID
* @param accessKeySecret 从STS服务获取的临时访问密钥AccessKey Secret
* @param roleArn 指定角色的ARN
* @param roleSessionName 时临时Token的会话名称,自己指定用于标识你的用户,或者用于区分Token颁发给谁
* @param durationSeconds token 有效事件,单位:秒
* @param policy 指定的授权策略 默认为null
* @return
* RequestId, 请求id
* AssumedRoleUser: {
* Arn, ${roleArn}/${roleSessionName}
* AssumedRoleId
* },
* Credentials: {
* SecurityToken, sts token
* AccessKeyId, accessKeyId
* AccessKeySecret, accessKeySecret
* Expiration 过期时间
* }
*/
export default function generateSTSToken(accessKeyId, accessKeySecret, roleArn, roleSessionName = 'external-username', durationSeconds = 3600, policy = null) {
const sts = new StsClient({
endpoint: 'sts.aliyuncs.com', // check this from sts console
accessKeyId, // check this from aliyun console
accessKeySecret // check this from aliyun console
});
return res = await sts.assumeRole(roleArn, roleSessionName, policy, durationSeconds);
generateSTSToken
me explain some of the input parameters of the 06198f161a55fb function. Usually when we use Alibaba Cloud or Tencent Cloud, we usually open a RAM
account, which is also a sub-account. After we log in to the Cloud backend with a sub-account, we will go to 16198f161a5600 object storage. (OSS) console page , find security token (sub-account authorization) , which is the place marked in the figure below, click above to go to RAM console button
Then click start authorizing button, and then you can get accessKeyId
, accessKeySecret
, roleArn
, roleSessionName
and the default expiration time DurationsSeconds
, as shown in the figure below, because I authorized once before, there will be a prompt in the lower left corner. All parameters must be saved, should not be leaked. Once leaked, please change the RAM account password and regenerate to invalidate the previous ones.
Improve the data provided by the server
At this time, the four parameters accessKeyId
, accessKeySecret
, stsToken
, expiration
But the client also needs the two parameters bucket
: object storage namespace and region
: bucket
location
This bucket
is actually the corresponding bucket
, which can be seen on the Alibaba Cloud Object Storage page. There is a bucket
, which is the name bucket
region
is the area where a certain bucket
is located, for example, my one is oss-cn-beijing
At this point, the work of the server is finished, and an interface can be provided on the front end. After passing the authentication, it returns to the front end with several parameters. Next, let's hand the stage to our front end~
{
accessKeyId,
accessKeySecret,
stsToken,
bucket,
region,
expiration
}
Front-end work
Well, the work of our back-end classmates has been completed~
The front-end guys come and draw a dragon on my left and a rainbow on your right (bushi)
First, we also create a new oss-sts-client.js/ts
, and then install a ali-sdk/ali-oss: Aliyun OSS (open storage service) JavaScript SDK for the browser and Node.js (github.com) package, yes, it does not support IE10 and The previous version of IE
npm install ali-oss --save
Then copy the following content to this file, students who use js can delete the ts-related code (change to TS quickly, no one will play with you)
// 这个是服务端提供给前端的一个请求接口,返回上面我们提到的几个参数
import { getOssSTSToken } from "./request";
// @ts-ignore 忽略ts报错,ali-oss赶紧提供@types包吧,文档难看懂,库也没个文档,你们文档要是维护的好,我还用写这个?我都不想吐槽……(bushi)
import OSS from 'ali-oss'
type OssStsType = {
accessKeyId: string
accessKeySecret: string
stsToken: string
expiration: number // 这个是前端计算出的还有多少秒token过期
region: string
bucket: string
}
/**
* 获取OSSClient
* @param accessKeyId AccessKey ID
* @param accessKeySecret 从STS服务获取的临时访问密钥AccessKey Secret
* @param stsToken 从STS服务获取的安全令牌(SecurityToken)
* @param region Bucket所在地域
* @param bucket Bucket名称
*/
export default async function getOssClient () {
const { code, data: params } = await getOssSTSToken();
if (code !== 200) return false; // 如果请求出错,在上游处理
const client = new OSS({
...params,
refreshSTSTokenInterval: params.expiration,
// 刷新临时访问凭证的时间间隔,单位为毫秒。
//(这个refreshSTSToken是文档里的,为了保险各位可以在每次上传前先检查一次过期没有,不要依赖提供的这个方法)
refreshSTSToken: async () => {
const { code, data } = await getOssSTSToken(); // 过期后刷新token
if (code === 200) {
return data
}
},
})
return client
}
Okay, so far we have encapsulated the method that this front-end needs to call when uploading files
Front-end maintenance of STS Token
First of all, when we upload a file on the front-end page for the first time, we need to call the getOssClient
method to oss-client
the object instance 06198f161a57cb before we can use this instance for uploading. After uploading, we need to first judge whether token
expired. If it has not expired, Still use this instance to upload, if it expires, regenerate an instance!
Here we take a simple upload of a small file as an example ( large file upload , and upload success callback (requires back-end students to provide the callback address) can see document , I will not go into details NS)
async function uploadFileAction(file, client) {
let newClient = client;
// 伪代码:
// if (!newClient || token is expired) { // 如果是没有实例对象或者token过期了就要重新生成
// newClient = await getOssClient(); // 调用上面我们封装好的一个方法
// }
const filePath = 'xxx/xxx/' // 最中在bucket中的存放的路径根据业务需要自行设置,文件名也是可以自行设置
const { res, name, url } = await newClient.put(`${filePath}${file.name}`, file);
if (res.status === 200) {
// 这里拿到上传成功的文件的url
return url
}
}
Regarding oss-client
, you will see the benevolent and the wise. There are many solutions, how to fit the business, but it is not recommended to store STS token
localStorage
and sessionStorage
and indexDB
. How can you be sure that your user is not the same? What about the front-end er?
CORS problem
It’s not over yet, xdm, wait a minute, after all the above is done, we still have CORS problems if we don’t open a proxy when we are in the local joint debugging. At this time, we still have to go to the server to configure, find the cross-domain settings, and go in to create A rule, the method depends on what you use to tick it, source and allow Headers
directly to dry *
it's done
Summarize
After the author is in contact with Ali cloud front-end and back-end document students look forward pass documents to see scalp of numb completely numb of Ma Ma in after, a summary of the front and rear end The OSS front-end direct transfer articles that can be opened up through the process, if you have any questions, welcome to discuss in the comments, if it can help you, give us a three-link
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。