中育新版本OSS Token获取API分析
在8/28更新中(或更早),中育彻底停用了旧版本的GenerateTokenAsync
API,转而使用GenerateTokenV2Async
API,新的API使用了签名和一些不明所以的参数,并可能限制了可以上传的路径。
为了尽快迁移旧的工具、程序,我对web端的OSS逻辑进行了分析。
源代码
在web端文件中直接搜索GenerateTokenV2Async
就可以找到一段代码:
function(e, t, n) {"use strict";n(180),n(79),n(54),n(11),n(153),n(34),n(71),n(754),n(85),n(75),n(36),n(43),n(10),n(62),n(108),n(44),n(45),n(110),n(109);var r = n(132),o = n.n(r),i = n(846),a = n(908),u = n(3172),l = n.n(u),s = n(220),c = n.n(s),f = n(4);function d(e, t) {var n = Object.keys(e);if (Object.getOwnPropertySymbols) {var r = Object.getOwnPropertySymbols(e);t && (r = r.filter((function(t) {return Object.getOwnPropertyDescriptor(e, t).enumerable}))),n.push.apply(n, r)}return n}function p(e) {for (var t = 1; t < arguments.length; t++) {var n = null != arguments[t] ? arguments[t] : {};t % 2 ? d(Object(n), !0).forEach((function(t) {h(e, t, n[t])})) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : d(Object(n)).forEach((function(t) {Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t))}))}return e}function h(e, t, n) {return t in e ? Object.defineProperty(e, t, {value: n,enumerable: !0,configurable: !0,writable: !0}) : e[t] = n,e}function m(e, t, n, r, o, i, a) {try {var u = e[i](a),l = u.value} catch (e) {return void n(e)}u.done ? t(l) : Promise.resolve(l).then(r, o)}function y(e) {return function() {var t = this,n = arguments;return new Promise((function(r, o) {var i = e.apply(t, n);function a(e) {m(i, r, o, a, u, "next", e)}function u(e) {m(i, r, o, a, u, "throw", e)}a(void 0)}))}}var v, g, b = n(3173);function _(e) {return f.b.post("/api/services/app/ObjectStorage/GenerateTokenV2Async", e)}function w(e, t, n, r, o) {return e.multipartUpload(t, n, r).then((function(t) {if (o && o(),null != t && t.name)return "".concat(e.options.endpoint.protocol, "//").concat(e.options.bucket, ".").concat(e.options.endpoint.host, "/").concat(t.name);throw new Error("上传失败")})).catch((function() {throw e = null,o && o(),new Error("上传失败")}))}function S(e, t, n, r) {return e.put(t, n).then((function(e) {return r && r(),e.url})).catch((function() {throw e = null,r && r(),new Error("上传失败")}))}function E(e, t, n, r) {return O.apply(this, arguments)}function O() {return (O = y(regeneratorRuntime.mark((function e(t, n, r, o) {return regeneratorRuntime.wrap((function(e) {for (;;)switch (e.prev = e.next) {case 0:return e.abrupt("return", new Promise((function(e, i) {var a = new FormData;a.append("file", r);var u = "".concat(t.endpoint, "/").concat(n);c.a.post(u, a, {headers: {EzyToken: "bearer ".concat(t.stsToken),Checksum: "3f4e17759c6b9c6a364211895bbb2abdc0ba62db"}}).then((function(r) {if (200 !== r.status)throw new Error("HTTP ".concat(r.status, ": ").concat(r.statusText));try {o && o();var a = "".concat(t.endpoint, "/").concat(n);e(a)} catch (e) {o && o(),i(new Error("服务器响应格式错误"))}})).catch((function(e) {o && o(),i(new Error("上传失败!"))}))})));case 1:case "end":return e.stop()}}), e)})))).apply(this, arguments)}function k() {return (k = y(regeneratorRuntime.mark((function e(t, n, r, o, i) {var a, u, l, s;return regeneratorRuntime.wrap((function(e) {for (;;)switch (e.prev = e.next) {case 0:if (!((a = r.size / 1024 / 1024) > o.maxSize)) {e.next = 3;break}throw new Error("附件大小不能超过".concat(o.maxSize, "M"));case 3:if (e.prev = 3,"ZYFS" !== (null === (u = t) || void 0 === u ? void 0 : u.strategy)) {e.next = 12;break}return e.next = 7,E(t, n, r, i);case 7:if (l = e.sent) {e.next = 10;break}throw new Error("上传失败");case 10:return t = null,e.abrupt("return", l);case 12:if (!(a > 51200 || o.type)) {e.next = 14;break}return e.abrupt("return", w(t, n, r, o, i));case 14:return e.next = 16,S(t, n, r, i);case 16:if (s = e.sent) {e.next = 19;break}throw new Error("上传失败");case 19:return t = null,e.abrupt("return", s);case 23:e.prev = 23,e.t0 = e.catch(3);case 25:return e.abrupt("return", null);case 26:case "end":return e.stop()}}), e, null, [[3, 23]])})))).apply(this, arguments)}function C() {return (C = y(regeneratorRuntime.mark((function e(t) {var n, r, u, s;return regeneratorRuntime.wrap((function(e) {for (;;)switch (e.prev = e.next) {case 0:return n = Object(a.a)(),r = n.id,(u = p(p({}, t), {}, {nonce: Object(i.a)().replace(/-/g, ""),ts: Date.now(),sign: ""})).sign = o.a.MD5("".concat(r, "+").concat(v[t.fc], "+").concat(g[t.fr], "+").concat(t.ft, "+").concat(t.fe, "+").concat(t.fo, "+").concat(u.nonce, "+").concat(u.ts)).toString().toUpperCase(),e.next = 5,_(u);case 5:if ("ZYFS" !== (s = e.sent).strategy) {e.next = 8;break}return e.abrupt("return", {fileId: u.nonce,path: "".concat(v[t.fc], "/").concat(g[t.fr], "/").concat(r, "/").concat(l()().format("YYYYMMDD"), "/").concat(u.nonce).concat(u.fe),ossClient: {endpoint: s.endpoint,strategy: s.strategy,stsToken: s.securityToken,expiration: s.expiration}});case 8:return e.abrupt("return", {fileId: u.nonce,path: "".concat(v[t.fc], "/").concat(g[t.fr], "/").concat(r, "/").concat(l()().format("YYYYMMDD"), "/").concat(u.nonce).concat(u.fe),ossClient: new b({region: s.region,bucket: s.bucket,stsToken: s.securityToken,accessKeyId: s.accessKeyId,accessKeySecret: s.accessKeySecret})});case 9:case "end":return e.stop()}}), e)})))).apply(this, arguments)}! function(e) {e[e.note_v2 = 1] = "note_v2",e[e.eval_v2 = 2] = "eval_v2",e[e.quora_v2 = 3] = "quora_v2",e[e.mistake_v2 = 4] = "mistake_v2",e[e.study_v2 = 5] = "study_v2",e[e.column_v2 = 6] = "column_v2",e[e.paper_v2 = 7] = "paper_v2",e[e.revise_v2 = 8] = "revise_v2",e[e.selection_v2 = 9] = "selection_v2",e[e.manage_v2 = 19] = "manage_v2"}(v || (v = {})),function(e) {e[e.res = 1] = "res",e[e.log = 2] = "log",e[e.other = 3] = "other"}(g || (g = {})),t.a = {upload: function(e, t, n, r, o) {return k.apply(this, arguments)},getUploadConfig: function(e) {return C.apply(this, arguments)}}
},
初步分析
读代码可以看出,新的API有下面几个参数:
- 文件分类
fc
fr
ft
fe
fo
ts
nonce
sign