This article allows you to completely store the front-end direct transmission of OSS with objects. If you don't understand it, read it again! (bushi)

Reason

In projects, we sometimes encounter problems related to uploading files. Generally, the back end provides an interface, and then when we upload, the back end sends it to Alibaba OSS or other service providers for object storage, and then saves the final url or returns it to the front end. In fact, 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 photo album and resource provider, in short, there are scenes where files are uploaded frequently, and the bandwidth of the server may be a little overwhelmed. Is there a better solution?

Server signature, client direct transmission

In fact, cloud service providers such as Alibaba, Tencent and qiniu all provide services similar to Alibaba STS(Security Token Service) temporary access rights management service This time, taking Alibaba cloud as an example, I'd like to introduce how to use STS token to enable the server to sign the STS token and then provide it to the front end, so that the front end can directly use this Token to transfer files to Alibaba cloud

The server signs and obtains the STS token

Let's take Node.js as an example. Services in other languages can be found in Alicloud SDK reference (STS) document There are Python, Java

First, we need to install one 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 to generate STS tokens for front-end use (this is only used as an example, and you can encapsulate them later)

const StsClient = require('@alicloud/sts-sdk');

/**
 * Generate STStoken
 * @param accessKeyId AccessKey ID
 * @param accessKeySecret Temporary access key obtained from STS Service AccessKey Secret
 * @param roleArn Specifies the ARN for the role
 * @param roleSessionName The session name of the temporary Token is specified to identify your user or to distinguish who the Token is issued to
 * @param durationSeconds token Valid events in seconds
 * @param policy The specified authorization policy defaults to null
 * @return
 *   RequestId, Request id
 *   AssumedRoleUser: {
 *     Arn, ${roleArn}/${roleSessionName}
 *     AssumedRoleId
 *   },
 *   Credentials: {
 *     SecurityToken, sts token
 *     AccessKeyId, accessKeyId
 *     AccessKeySecret, accessKeySecret
 *     Expiration Expiration time
 *   }
 */
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);

Let me explain some parameters of the generatetoken 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 Alibaba cloud background with the sub account, we Object store (OSS) console page , find the security token (sub account authorization), that is, the place marked in the figure below, and click the go to RAM console button above

Then click the start authorization button. After that, you can get accessKeyId, accessKeySecret, roleArn, roleSessionName and the default expiration time durationseconds, as shown in the figure below. Since I have authorized once before, there will be a prompt in the lower left corner. These parameters must be saved and not disclosed. Once disclosed, please change the RAM account password, And regenerate to invalidate the previous

Improve the data provided by the server

At this time, you have actually obtained the four parameters of accessKeyId, accessKeySecret, stsToken and expiration

However, the client also needs two parameters: bucket: the namespace stored by the object and region: the region where the bucket is located

This bucket is actually the corresponding bucket. This can be seen on the Alibaba cloud object storage page. There is a bucket list, which is the name of the bucket you want to use

Region is the region where a bucket is located. For example, my region is OSS CN Beijing

At this time, the work of the server is finished. You can provide an interface to the front end. After authentication, you can return these parameters to the front end. Next, let's hand over the stage to our front end~

{
  accessKeyId,
  accessKeySecret,
  stsToken,
  bucket,
  region,
  expiration
}

Front end work

Well, our back-end students have finished their work~

Let's draw a dragon on my left and a rainbow on your right

First, we also create an oss-sts-client.js/ts, and then install one ali-sdk/ali-oss: Aliyun OSS(open storage service) JavaScript SDK for the browser and Node.js (github.com) By the way, IE10 and previous IE versions are not supported

npm install ali-oss --save

Then copy the following content to this file. Students using js can delete the code related to TS (quickly change to TS, and no one will play with you if you don't change it)

// This is a request interface provided by the server to the front end, which returns several parameters mentioned above
import { getOssSTSToken } from "./request"; 
// @ts ignore ignores the ts error, and Ali OSS quickly provides the @ types package. The document is difficult to understand, and there is no document in the library. If your document is well maintained, I still need to write this? I don't want to make complaints about it. (bushi)
import OSS from 'ali-oss'

type OssStsType = {
  accessKeyId: string
  accessKeySecret: string
  stsToken: string
  expiration: number // This is calculated by the front end. How many seconds does the token expire
  region: string
  bucket: string
}

/**
 * Get OSSClient
 * @param accessKeyId AccessKey ID
 * @param accessKeySecret Temporary access key obtained from STS Service AccessKey Secret
 * @param stsToken Security token obtained from STS Service (SecurityToken)
 * @param region Bucket Location
 * @param bucket Bucket name
 */
export default async function getOssClient () {
  const { code, data: params } = await getOssSTSToken();
  if (code !== 200) return false; // If the request goes wrong, it is processed upstream
  const client = new OSS({
    ...params,
    refreshSTSTokenInterval: params.expiration,
    // The time interval, in milliseconds, between refreshing temporary access credentials.
    //(this refreshtoken is in the document. To ensure safety, you can check whether it has expired before uploading each time. Don't rely on the method provided.)
    refreshSTSToken: async () => {
      const { code, data } = await getOssSTSToken(); // Refresh token after expiration
      if (code === 200) {
        return data
      }
    },
  })
  return client
}

Well, so far, we have encapsulated the methods that the front end needs to call when uploading files

Front end maintenance STS Token

First, when uploading files on the front-end page for the first time, we need to call the getOssClient method to obtain the OSS client object instance before uploading with this instance. Then, when uploading, we need to judge whether the token has expired. If not, we still use this instance for uploading. If it has expired, we will regenerate an instance!

Here, let's take a simple example of uploading a small file (large file piecemeal upload and successful upload callback (the callback address needs to be provided by the back-end students). You can see it yourself file , I won't elaborate)

async function uploadFileAction(file, client) {
  let newClient = client;
  // Pseudo code:
  // If (! Newclient | token is expired) {/ / if there is no instance object or the token is expired, it needs to be regenerated
  //  newClient = await getOssClient(); / / call the method we encapsulated above
  // }
  const filePath = 'xxx/xxx/' // The storage path in the bucket can be set according to business needs, and the file name can also be set by yourself
  const { res, name, url } = await newClient.put(`${filePath}${file.name}`, file);
  if (res.status === 200) {
    // Here you can get the url of the successfully uploaded file
    return url
  }  
}

As for the OSS client maintenance strategy here, different people have different opinions. There are many schemes, how to fit the business, but it is not recommended to store STS token and other parameters in localStorage, sessionStorage and indexDB. How can you make sure that your user is not a front-end user?

Problems with CORS

It's not over yet. xdm wait a minute. After all the above, if we don't open the agent during local joint commissioning, there will still be CORS problems. At this time, we still have to go to the server to configure, find cross domain settings, go in and create a rule. The method depends on what you tick, and the source and allow Headers to do * directly


summary

After contacting Alibaba cloud's front-end direct transmission documents, the author also reviewed the documents with the back-end students and saw that the scalp was numb. After it was completely numb, the author summarized an OSS front-end direct transmission article that can get through the front-end and back-end processes. If you have any questions, you are welcome to discuss them in the comments. If you can help, let's have a three connection

Keywords: node.js Front-end Alibaba Cloud oss

Added by fubowl on Sat, 20 Nov 2021 17:13:51 +0200