ali-oss( Browser.js SDK)踩(吐)坑(槽)记录

踩坑记录

1、refreshSTSTokenInterval 不生效

官方初始化文档中没有此配置项,但是在某个例子中写了这个属性。

既然是间隔,那我就设置 15*60*60*100015分钟吧,
【bug描述】 还没有到token过期时间,但是每一个 put(上传)和 signatureUrl(下载)操作都会重新请求token。
文档中没有此配置项
初始化示例

2、refreshSTSToken 刷新了token,但是下载文件token失效

【bug描述】:调用refreshSTSToken 后,获取到token,在下次操作才生效。也就是: token到期之前的值是a,到期后重新发送请求获取到的token是b,但是signatureUrl返回的文件地址中的token仍然是a,下载文件的时候就会提示token失效。再一次点击下载文件,url中的token是b,又可以正常下载了。

解决了refreshSTSTokenInterval 刷新间隔问题后,这个诡异的bug改的我怀疑自己的码代码水平了。

根本bug原因:Browser.js代码

  1. refreshSTSTokenInterval 不生效
    【bug原因】: 用时间戳 和 时间间隔比大小

  2. refreshSTSToken 刷新了token,但是下载文件token失效
    【bug原因】:同步的方法里执行异步请求,然后就没然后了
    signatureUrl 部分源代码如下

var proto = exports;
proto.signatureUrl = function signatureUrl(name, options) {
  // 略....

  if (this.options.stsToken && isFunction(this.options.refreshSTSToken)) {
  // 当前时间
    var now = new Date();
	/**
	 1、refreshSTSTokenInterval 不生效 bug原因:
	 用时间戳 和 时间间隔比大小,写这个代码的人咋想到的???????
	**/
    if (this.stsTokenFreshTime >= this.options.refreshSTSTokenInterval) {
      this.stsTokenFreshTime = now;
      /*
      	这里假设 refreshSTSTokenInterval 是生效的,刷新间隔15分钟到了以后 refreshSTSToken
      	2、refreshSTSToken 刷新了token,但是下载文件token失效 bug原因:
      	逗我玩呢?这里调用了个异步方法请求token,然后同步代码去拼接url,异步请求回来啥也不干了???? 
      	这操作就相当于有人告诉你办公室的钥匙换了,于是你去跟物业说:“给我一把新钥匙”。
      	也不等物业给你钥匙,说完自己就走了,继续用旧钥匙开门。
		*/
      this.options.refreshSTSToken().then(function (r) {
        var credentials = formatObjKey(r, 'firstLowerCase');

        if (credentials.securityToken) {
          credentials.stsToken = credentials.securityToken;
        }

        checkCredentials(credentials);
        Object.assign(_this.options, credentials);
      });
    } else {
      this.stsTokenFreshTime = now;
    }
  }

  if (this.options.stsToken) {
    options['security-token'] = this.options.stsToken;
  }

  var signRes = signHelper._signatureForURL(this.options.accessKeySecret, options, resource, expires);

  var url = urlutil.parse(this._getReqUrl(params));
  url.query = {
    OSSAccessKeyId: this.options.accessKeyId,
    Expires: expires,
    Signature: signRes.Signature
  };
  copy(signRes.subResource).to(url.query);
  return url.format();
};

解决方案

import OSS from "ali-oss";
import { getOssToken } from "@/api/fileTransmit";

class Client {
  client = null;

  _tokenExpiredTime = 0;
  _token = null;
  _promise = null;

  get token() {
  	// 【解决bug】refreshSTSTokenInterval 不生效
  	// 【解决方案】根据请求返回的Expiration时间判断是否过期,没有token的时候调用getAccess方法获取getOssToken 
    if (Date.now() >= this._tokenExpiredTime || this._token === null) {
      return null;
    } else {
      return { ...this._token };
    }
  }
  set token(value) {
   // 设置token
    this._token = value;
    // 设置token过期时间
    this._tokenExpiredTime = new Date(value.Expiration).getTime();
    //【解决bug】refreshSTSToken 刷新了token,但是下载文件token失效
    //【解决方案】如果已经初始化了,强制修改ossClient中存储的token。
    if (this.client) {
      this.client.options.stsToken = value.stsToken;
      this.client.options.accessKeyId = value.accessKeyId;
      this.client.options.accessKeySecret = value.accessKeySecret;
    }
  }
  /**
   * 请求token
   */
  async requestAccess() {
    // 【解决bug】refreshSTSTokenInterval 不生效
  	// 【解决方案】根据请求返回的Expiration时间判断是否过期,过期调用getOssToken 重新获取token,没有过期就使用存储的token
    // 此处代码时配置的oss自动定时刷新不生效,所以在这里自己手动定时刷新
    if (!this.token) {
      this.token = await getOssToken();
    }
    return this.token;
  }
  /**
   * 获取token队列
   */
  getAccess() {
    // 如果已经正在请求token,就返回正在请求的方法
    if (this._promise) {
      return this._promise;
    }
    this._promise = new Promise(async (resolve) => {
      const res = await this.requestAccess();
      this._promise = null;
      resolve(res);
    });
    return this._promise;
  }
  /**
   * oss初始化
   */
  async init() {
    try {
      const access = await this.getAccess(true);
      this.client = new OSS({
        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
        region: "yourRegion",
        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
        accessKeyId: access.accessKeyId,
        accessKeySecret: access.accessKeySecret,
        // 从STS服务获取的安全令牌(SecurityToken)。
        stsToken: access.stsToken,
        refreshSTSToken: this.getAccess.bind(this),
        // 刷新临时访问凭证的时间间隔,单位为毫秒。
        // refreshSTSTokenInterval: 15 * 60 * 1000,
        // 填写Bucket名称。
        bucket: "填写Bucket名称。"
      });
    } catch (e) {
      throw new Error("获取oss凭证失败");
    }
  }

  /**
   * 上传
   * @param {string} filename  上传的文件
   * @param {File} file  上传的文件
   * @return { {name: string, url: string} }
   */
  async upload(filename, file) {
    if (!this.client) {
      await this.init();
    }
    // 【解决bug】refreshSTSTokenInterval 不生效
  	// 【解决方案】每次上传文件之前读取token
    await this.getAccess();
    const headers = { "x-oss-forbid-overwrite": "false" };
    try {
      const res = await this.client.put(filename, file, { headers });
      if (res.message) {
        throw res;
      }
      return { name: res.name, url: res.url };
    } catch (e) {
      throw e;
    }
  }
  /**
   * 下载
   * @param {string} filename  下载的文件名
   * @return { string } 下载地址
   */
  async getResourceUrl(filename) {
    if (!this.client) {
      await this.init();
    }
    // 【解决bug】refreshSTSTokenInterval 不生效
  	// 【解决方案】每次下载文件之前读取token
    await this.getAccess();
    const response = {
      "content-disposition": `attachment;`
    };
    try {
      const url = await this.client.signatureUrl(filename, { response });
      if (typeof url === "string") {
        return url;
      } else {
        throw url;
      }
    } catch (e) {
      throw e;
    }
  }
}

其他功能暂未使用,要是后续使用过程中发现新bug,还会继续更新
希望能帮助到使用ali-oss( Browser.js SDK)的打工人

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值