小程序 阿里云OSS 基于服务器校验的情况

网上搜了很多,发现小程序连接OSS是使用的 长期的OSSAccessKeyID的方案,然后403一大堆

但是本着不给运营大佬造成风险

不给后端大佬添麻烦的美丽愿景

直接使用自己写移动端的请求方式

记录下这个方案

upload.js

const env = require('config.js'); //配置文件,在这文件里配置你的OSS keyId和KeySecret,timeout:87600;

const base64 = require('base64.js');//Base64,hmac,sha1,crypto相关算法

require('hmac.js');

require('sha1.js');

const Crypto = require('crypto.js');

const request  =require('request.js')

var app = getApp()

/*

*上传文件到阿里云oss

*@param - filePath :图片的本地资源路径

*@param - dir:表示要传到哪个目录下

*@param - successc:成功回调

*@param - failc:失败回调

*/

const uploadFile = function (filePath, dir, successc, failc) {

  if (!filePath || filePath.length < 9) {

      wx.showModal({

        title: '图片错误',

        content: '请重试',

        showCancel: false,

      })

      return;

  }

  console.log('上传图片.....');

  //图片名字 可以自行定义,    这里是采用当前的时间戳 + 150内的随机数来给图片命名的

  const aliyunFileKey = dir + new Date().getTime() + Math.floor(Math.random() * 150) + '.png';

  const aliyunServerURL = env.uploadImageUrl;//OSS地址,需要https

  const policyBase64 = getPolicyBase64();

  console.log(app.globalData.bus.jwt)

  request.request('/user/get_upload_token',{},function(e){ //从后端获取签名,可以用wx.request()替代

      const signature = getSignature(policyBase64,e.data.data.accessKeySecret);//获取签名

      wx.uploadFile({

      url: aliyunServerURL,//开发者服务器 url

      filePath: filePath,//要上传文件资源的路径

      name: 'file',//必须填file

      formData: {

          'key':aliyunFileKey,

          'policy':policyBase64,

          'OSSAccessKeyId':e.data.data.accessKeyId,

          'signature':signature,

          'success_action_status': '200', //不提供会204

          'x-oss-security-token':e.data.data.securityToken

      },

      success: function (res) {

          if (res.statusCode != 200) {

            failc(new Error('上传错误:' + JSON.stringify(res)))

            return;

          }

          successc(aliyunServerURL + '/'+aliyunFileKey);

      },

      fail: function (err) {

          err.wxaddinfo = aliyunServerURL;

          failc(err);

      },

    })



  },function(res){})

}

const getPolicyBase64 = function () {

  let date = new Date();

  date.setHours(date.getHours() + env.timeout);

  let srcT = date.toISOString();

  const policyText = {

      "expiration": srcT, //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了

      "conditions": [

        ["content-length-range", 0, 5 * 1024 * 1024] // 设置上传文件的大小限制,5mb

      ]

  };

  const policyBase64 = base64.encode(JSON.stringify(policyText));

  return policyBase64;

}

const getSignature = function (policyBase64,security) {

  const accesskey = security;

  const bytes = Crypto.HMAC(Crypto.SHA1, policyBase64, accesskey, {

      asBytes: true

  });

  const signature = Crypto.util.bytesToBase64(bytes);

  return signature;

}

module.exports = uploadFile;

其他相关文件

crypto.js

const Crypto = {};

(function(){

var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";


// Crypto utilities
var util = Crypto.util = {

    // Bit-wise rotate left
    rotl: function (n, b) {
        return (n << b) | (n >>> (32 - b));
    },

    // Bit-wise rotate right
    rotr: function (n, b) {
        return (n << (32 - b)) | (n >>> b);
    },

    // Swap big-endian to little-endian and vice versa
    endian: function (n) {

        // If number given, swap endian
        if (n.constructor == Number) {
            return util.rotl(n,  8) & 0x00FF00FF |
                   util.rotl(n, 24) & 0xFF00FF00;
        }

        // Else, assume array and swap all items
        for (var i = 0; i < n.length; i++)
            n[i] = util.endian(n[i]);
        return n;

    },

    // Generate an array of any length of random bytes
    randomBytes: function (n) {
        for (var bytes = []; n > 0; n--)
            bytes.push(Math.floor(Math.random() * 256));
        return bytes;
    },

    // Convert a string to a byte array
    stringToBytes: function (str) {
        var bytes = [];
        for (var i = 0; i < str.length; i++)
            bytes.push(str.charCodeAt(i));
        return bytes;
    },

    // Convert a byte array to a string
    bytesToString: function (bytes) {
        var str = [];
        for (var i = 0; i < bytes.length; i++)
            str.push(String.fromCharCode(bytes[i]));
        return str.join("");
    },

    // Convert a string to big-endian 32-bit words
    stringToWords: function (str) {
        var words = [];
        for (var c = 0, b = 0; c < str.length; c++, b += 8)
            words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32);
        return words;
    },

    // Convert a byte array to big-endian 32-bits words
    bytesToWords: function (bytes) {
        var words = [];
        for (var i = 0, b = 0; i < bytes.length; i++, b += 8)
            words[b >>> 5] |= bytes[i] << (24 - b % 32);
        return words;
    },

    // Convert big-endian 32-bit words to a byte array
    wordsToBytes: function (words) {
        var bytes = [];
        for (var b = 0; b < words.length * 32; b += 8)
            bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
        return bytes;
    },

    // Convert a byte array to a hex string
    bytesToHex: function (bytes) {
        var hex = [];
        for (var i = 0; i < bytes.length; i++) {
            hex.push((bytes[i] >>> 4).toString(16));
            hex.push((bytes[i] & 0xF).toString(16));
        }
        return hex.join("");
    },

    // Convert a hex string to a byte array
    hexToBytes: function (hex) {
        var bytes = [];
        for (var c = 0; c < hex.length; c += 2)
            bytes.push(parseInt(hex.substr(c, 2), 16));
        return bytes;
    },

    // Convert a byte array to a base-64 string
    bytesToBase64: function (bytes) {

        // Use browser-native function if it exists
        if (typeof btoa == "function") return btoa(util.bytesToString(bytes));

        var base64 = [],
            overflow;

        for (var i = 0; i < bytes.length; i++) {
            switch (i % 3) {
                case 0:
                    base64.push(base64map.charAt(bytes[i] >>> 2));
                    overflow = (bytes[i] & 0x3) << 4;
                    break;
                case 1:
                    base64.push(base64map.charAt(overflow | (bytes[i] >>> 4)));
                    overflow = (bytes[i] & 0xF) << 2;
                    break;
                case 2:
                    base64.push(base64map.charAt(overflow | (bytes[i] >>> 6)));
                    base64.push(base64map.charAt(bytes[i] & 0x3F));
                    overflow = -1;
            }
        }

        // Encode overflow bits, if there are any
        if (overflow != undefined && overflow != -1)
            base64.push(base64map.charAt(overflow));

        // Add padding
        while (base64.length % 4 != 0) base64.push("=");

        return base64.join("");

    },

    // Convert a base-64 string to a byte array
    base64ToBytes: function (base64) {

        // Use browser-native function if it exists
        if (typeof atob == "function") return util.stringToBytes(atob(base64));

        // Remove non-base-64 characters
        base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");

        var bytes = [];

        for (var i = 0; i < base64.length; i++) {
            switch (i % 4) {
                case 1:
                    bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) |
                               (base64map.indexOf(base64.charAt(i)) >>> 4));
                    break;
                case 2:
                    bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) |
                               (base64map.indexOf(base64.charAt(i)) >>> 2));
                    break;
                case 3:
                    bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) |
                               (base64map.indexOf(base64.charAt(i))));
                    break;
            }
        }

        return bytes;

    }

};

// Crypto mode namespace
Crypto.mode = {};

})();

module.exports = Crypto;

base64


var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
function encode(str) {
    var out, i, len;
    var c1, c2, c3;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt((c1 & 0x3) << 4);
            out += "==";
            break;
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            out += base64EncodeChars.charAt((c2 & 0xF) << 2);
            out += "=";
            break;
        }
        c3 = str.charCodeAt(i++);
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
        out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
        out += base64EncodeChars.charAt(c3 & 0x3F);
    }
    return out;
}
function decode(str) {
    var c1, c2, c3, c4;
    var i, len, out;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        /* c1 */
        do {
            c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        } while (i < len && c1 == -1);
        if (c1 == -1)
            break;
        /* c2 */
        do {
            c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        } while (i < len && c2 == -1);
        if (c2 == -1)
            break;
        out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
        /* c3 */
        do {
            c3 = str.charCodeAt(i++) & 0xff;
            if (c3 == 61)
                return out;
            c3 = base64DecodeChars[c3];
        } while (i < len && c3 == -1);
        if (c3 == -1)
            break;
        out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
        /* c4 */
        do {
            c4 = str.charCodeAt(i++) & 0xff;
            if (c4 == 61)
                return out;
            c4 = base64DecodeChars[c4];
        } while (i < len && c4 == -1);
        if (c4 == -1)
            break;
        out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    return out;
}


function utf16to8(str) {
    var out, i, len, c;
    out = "";
    len = str.length;
    for (i = 0; i < len; i++) {
        c = str.charCodeAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
            out += str.charAt(i);
        } else if (c > 0x07FF) {
            out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
            out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        } else {
            out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        }
    }
    return out;
}
function utf8to16(str) {
    var out, i, len, c;
    var char2, char3;
    out = "";
    len = str.length;
    i = 0;
    while (i < len) {
        c = str.charCodeAt(i++);
        switch (c >> 4) {
            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                // 0xxxxxxx
                out += str.charAt(i - 1);
                break;
            case 12: case 13:
                // 110x xxxx 10xx xxxx
                char2 = str.charCodeAt(i++);
                out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                break;
            case 14:
                // 1110 xxxx 10xx xxxx 10xx xxxx
                char2 = str.charCodeAt(i++);
                char3 = str.charCodeAt(i++);
                out += String.fromCharCode(((c & 0x0F) << 12) |
                    ((char2 & 0x3F) << 6) |
                    ((char3 & 0x3F) << 0));
                break;
        }
    }
    return out;
}


module.exports = {
    encode: encode,
    decode: decode,
    utf16to8: utf16to8,
    utf8to16: utf8to16
}

hmac.js

const Crypto = require('./crypto.js');

(function(){

// Shortcut
var util = Crypto.util;

Crypto.HMAC = function (hasher, message, key, options) {

    // Allow arbitrary length keys
    key = key.length > hasher._blocksize * 4 ?
          hasher(key, { asBytes: true }) :
          util.stringToBytes(key);

    // XOR keys with pad constants
    var okey = key,
        ikey = key.slice(0);
    for (var i = 0; i < hasher._blocksize * 4; i++) {
        okey[i] ^= 0x5C;
        ikey[i] ^= 0x36;
    }

    var hmacbytes = hasher(util.bytesToString(okey) +
                           hasher(util.bytesToString(ikey) + message, { asString: true }),
                           { asBytes: true });
    return options && options.asBytes ? hmacbytes :
           options && options.asString ? util.bytesToString(hmacbytes) :
           util.bytesToHex(hmacbytes);

};

})();

module.exports = Crypto;

util.js

const formatTime = date => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()

  return [year, month, day].map(formatNumber).join('/') + 'T' + [hour, minute, second].map(formatNumber).join(':')
}

const formatNumber = n => {
  n = n.toString()
  return n[1] ? n : '0' + n
}

module.exports = {
  formatTime: formatTime
}

config.js

var fileHost = "https://****.oss-cn-beijing.aliyuncs.com";//你的阿里云OSS地址  在你当前小程序的公众号后台的uploadFile 合法域名也要配上这个域名
var config = {
   uploadImageUrl: `${fileHost}`, // 默认存在根目录,可根据需求改
   bucketName:'corgi-pic',  // AccessKeyId 去你的阿里云上控制台上找
   timeout: 80000 //这个是上传文件时Policy的失效时间
};

module.exports = config

下面使用它,前面的所有我都放在了utils文件夹里

 addPic:function(){ //bindtap时间
    var that = this
    wx.chooseImage({
      count:9,
      complete: (res) => {
        var tempFilePaths = res.tempFilePaths;
        var nowTime = util.formatTime(new Date());
        //支持多图上传
        for (var i = 0; i < res.tempFilePaths.length; i++) {
           //显示消息提示框
           wx.showLoading({
              title: '上传中' + (i + 1) + '/' + res.tempFilePaths.length,
              mask: true
           })
           //上传图片
           //你的域名下的/cbb文件下的/当前年月日文件下的/图片.png
           //图片路径可自行修改
           uploadImage(res.tempFilePaths[i], 'bus/' + nowTime + '/',
              function (result) {
                 console.log("======上传成功图片地址为:", result);
                 that.addBusPic(result); //不重要,处理结果的方法
                 wx.hideLoading();
              }, function (result) {
                 console.log("======上传失败======", result);
                 //做你具体的业务逻辑操作
                 if(length==res.tempFilePaths.length){
                  
                }
                 wx.hideLoading()
              })
            }
      },
    })  

  },


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352