Web端直传实践
场景概述
VOD 用户通过Web上传,是VOD使用需求中很典型的一种应用场景。在该场景下,用户通常采用应用服务器中转的模型进行文件上传。
- 用户先将文件通过Web上传到应用服务器;
- 应用服务器再将文件上传到VOD。
这个模型的优点比较明显:
- 客户端和 VOD 服务器没有任何交互工作,所有和 VOD 的交互都由服务器完成,非常简单和安全;
- 服务器可以精确控制用户的行为,添加各种自定义流程。
但是这个模型的缺点也显而易见:
- 上传速度慢。因为需要经过应用服务器中转,与客户端数据直传到 VOD 相比,网络传送增加了一倍。
- 扩展性差。随着用户数量的增加,应用服务器可能成为传输瓶颈。
- 成本高。应用服务器的部署和维护需要一定成本,如客户端数据直传到VOD,将节省应用服务器的开销,且目前VOD上传的流量是免费的。
如果您的应用需要符合这个场景的话,我们推荐您使用"bce-bos-uploader"工具实现客户端直传VOD的方式。
bce-bos-uploader
Baidu Cloud Engine BOS Uploader(bce-bos-uploader)是百度智能云基于Javascript SDK开发的一个ui组件,为了方便用户开发web直传应用而专门提供的,使用该工具用很少的几行代码就可以完成跟BOS服务的对接。由于 VOD 服务依赖和集成了BOS服务,所以bce-bos uploader的一个git分支提供了一个3in1页面,对一个已经开启了BOS、VOD、DOC服务的用户,根据源文件类型智能的上传到BOS、VOD或者DOC服务。
本文重点讲述如何在3in1页面中直传VOD,用户可以根据实际需要对此3in1功能和界面进行自定义修改,详细操作参见在浏览器中直接上传文件到VOD。
bce-bos-uploader的demo操作界面如下:
支持的浏览器
基于Xhr2和File API,可以支持IE10+, Firefox,Chrome和Opera最新版。 借助PostObject接口,可以支持IE低版本(6,7,8,9),详细请参见:通过PostObject接口处理IE低版本。
签名方式
bce-bos-upload支持默认、STS、PostObject三种签名方式。
默认签名方式即使用AK/SK签名方式在浏览器中直接上传文件到 VOD 中。通过浏览器直传文件到VOD服务器的时候,如果把AK和SK暴露在页面中,会引发安全性的问题。攻击者获取了AK和SK,可以对VOD甚至百度智能云其他服务上面的数据进行任意的操作。这模式仅可用于开发期间进行本地测试,请勿在生产环境中使用。
使用STS签名更安全灵活,它可以对用户的使用权限进行灵活、精确地控制,而且不必每次请求都调用后端接口,在有效期内就可以不用再请求新的Security Token。
因为IE低版本(IE6,7,8,9)对 HTML5 API 支持的不完善,为了在这些浏览器里面实现文件直传的功能,VOD服务中的存储服务BOS提供了PostObject接口,支持了 multipart/form-data 的请求格式,方便在低版本的IE下面把文件上传到BOS服务器。
在浏览器中直接上传文件到VOD
使用bce-bos-uploader,可以参考下面的内容完成如何在浏览器中直接上传文件到VOD。
操作流程
- 注册百度智能云账号,实名认证,开通VOD服务。
-
查询ak/sk。
在百度智能云控制台首页右上角的“安全认证->Access Key” 查询AK和SK的信息,也可以在Bucket管理中查看。
-
初始化bce-bos-uploader参数。
获取bce-bos-uploader 通过github下载:https://github.com/baidubce/bce-bos-uploader/
-
修改moe/3in1.js中的:
var AK = getQuery('ak', '替换为你的AK'); var SK = getQuery('sk', '替换为你的SK');
并把整个包都部署到服务器上。
-
启动webserver
通过PHP来启动
php -S 0.0.0.0:9999通过Python来启动
python -m SimpleHTTPServer 9999
启动webserver之后,在浏览器里面访问 http://your_server:your_port/bce-bos-uploader-gh-pages/moe/3in1.html
打开刚才的页面,开始测试是否可以正常上传。
注意:
“moe/3in1.js” 是集合了百度智能云VOD、百度智能云DOC、百度智能云BOS的三合一服务。这个js的默认策略是:根据媒资后缀名的不同,自动上传至不同的服务。
- 后缀为avi、mp4、flv、rm、rmvb、webm类型的媒资,将上传到百度智能云VOD;
- 后缀为txt、pdf、doc、docx、ppt、pptx、xls、xlsx类型的文件,将上传到百度智能云DOC;
- 其余类型默认上传到BOS。以3in1.js中的实际方法为准。
为了达到自动分渠道这个目标,您需要合理配置DOC和BOS相关的服务,修改moe/3in1.js中的var VOD_EXTS、var DOC_EXTS、以及function getKey(file)方法,来实现自己的业务逻辑。
举例:如果您仅开通了VOD服务,只希望用这块代码上传VOD,可以修改”3in1.js”中的function getKey(file)方法,直接return getVodKey(file);
即可。
进阶篇一:STS临时认证
Bce-bos-uploader支持STS(Security Token Service)临时授权的方式。服务端生成一组具体特定操作权限、具有一定时效性的临时AK/SK,这组临时的AK/SK可以暴露给浏览器端直接使用。用户只需要将服务端返回的AK/SK及SessionToken设置为bce-bos-uploader对应的bos-ak、bos-sk和uptoken参数。
下图简单介绍了整个业务交互过程,关于STS方面的介绍请参考临时授权访问。
代码实现分为应用服务器端和客户端两部分,实现过程如下:
应用服务器端Nodejs实现
配置应用服务器端,以Nodejs实现为例,服务器端会返回AK/SK/SessionToken。 配置浏览器,根据服务器端返回的AK/SK/SessionToken初始化bce-bos-uploader参数。
应用服务器端Nodejs实现:
var http = require('http');
var url = require('url');
var util = require('util');
var STS = require('@baiducloud/sdk').STS;
var kCredentials = {
ak: '您的AK',
sk: '您的SK'
};
function buildStsResponse() {
var stsClient = new STS({
credentials: kCredentials,
region: 'bj'
});
return stsClient.getSessionToken(60 * 60 * 24, {
accessControlList: [{
service: 'bce:bos',
resource: ['vod-gcqgg7xk0eqr78je/*'],
region: '*',
effect: 'Allow',
permission: ['WRITE']
}]
}).then(function (response) {
var body = response.body;
return {
AccessKeyId: body.accessKeyId,
SecretAccessKey: body.secretAccessKey,
SessionToken: body.sessionToken,
Expiration: body.expiration
};
});
}
http.createServer(function (req, res) {
console.log(req.url);
var query = url.parse(req.url, true).query;
var promise = null;
if (query.sts) {
promise = buildStsResponse();
}
promise.then(function (payload) {
res.writeHead(200, {
'Content-Type': 'text/javascript; charset=utf-8',
'Access-Control-Allow-Origin': '*'
});
if (query.callback) {
res.end(util.format('%s(%s)', query.callback, JSON.stringify(payload)));
}
else {
res.end(JSON.stringify(payload));
}
});
}).listen(1337);
console.log('Server running at http://0.0.0.0:1337/');
注意:
resource: ['vod-gcqgg7xk0eqr78je/*']
这一行需要自定义,具体参考STS和VOD、BOS的关系。
在服务器端,用与创建bosClient实例类似的方式创建一个stsClient实例。对于stsClient实例,主要有一个方法,那就是getSessionToken。这个方法接收两个参数,第一个参数是临时授权的有效期,以秒为单位;第二个单位是具体的权限控制。
这个方法会异步访问STS授权服务器,返回一个promise对象。STS授权服务器会返回类似如下内容:
{
body: {
"accessKeyId": "d87a16e5ce1d47c1917b38ed03fbb329",
"secretAccessKey": "e9b6f59ce06c45cdaaea2296111dab46",
"sessionToken": "MjUzZjQzNTY4OTE0NDRkNjg3N2E4YzJhZTc4YmU5ZDh8AAAAABwCAAB/HfHDVV2bu5xUf6rApt2YdSLG6+21UTC62EHvIuiaamtuMQQKNkR9PU2NJGVbuWgBn8Ot0atk0HnWYQGgwgyew24HtbrX3GFiR/cDymCowm0TI6OGq7k8pGuBiCczT8qZcarH7VdZBd1lkpYaXbtP7wQJqiochDXrswrCd+J/I2CeSQT6mJiMmvupUV06R89dWBL/Vcu7JQpdYBk0d5cp2B+gdaHddBobevlBmKQw50/oOykJIuho4Wn7FgOGPMPdod0Pf0s7lW/HgSnPOjZCgRl0pihs197rP3GWpnlJRyfdCY0g0GFG6T0/FsqDbxbi8lWzF1QRTmJzzh2Tax8xoPFKGMbpntp//vGP7oPYK1JoES34TjcdcZnLzIRnVIGaZAzmZMUhPEXE5RVX1w8jPEXMJJHSrFs3lJe13o9Dwg==",
"createTime": "2016-02-16T14:01:29Z",
"expiration": "2016-02-16T15:41:29Z",
"userId": "5e433c4a8fe74765a7ec6fc147e25c80"
}
}
服务器端需要把accessKeyId、secretAccessKey、sessionToken三个字段下发给浏览器端。
配置浏览器端bce-bos-uploader参数
使用STS临时授权机制时,只需要在各个服务初始化的时候把上面所说的参数accessKeyId、secretAccessKey、sessionToken引入就可以了。对3in1.html来说,就是在服务器向客户端分发3in1.js时候,修改掉其中的
var AK = getQuery('ak', '您从STS申请到的临时AK'); var SK = getQuery('sk', '您从STS申请到的临时SK '); var SESSION_TOKEN = '您从STS申请到的临时token';
以及对3in1.js代码中的多处 // uptoken: SESSION_TOKEN, 中的uptoken解除注释。
再次测试,在浏览器中抓包,发现authorization头中有x-bce-security-token字样,且成功,说明STS模式直传VOD测试成功。
进阶篇二:通过PostObject接口处理IE低版本
VOD服务中,上传服务是基于BOS来提供。
因为IE低版本(IE8,IE9)对html5支持的不完善,为了在这些浏览器里面实现文件直传的功能,BOS开发了PostObject接口,通过一个multipart/form-data的格式,就可以把文件上传到BOS服务器。Postobject接口的签名模式下应用服务器端对policy生成签名,再返回给客户端。
bce-bos-uploader已经实现了对这个接口的支持,使用之前需要进行额外的配置工作。
服务器端返回uptoken_url参数: 使用PostObject处理IE低版本时,需要在bce-bos-uploader中配置uptoken_url参数,关于 uptoken_url如何实现详细代码请参见uptoken代码示例。
然后修改3in1.js:
var UPTOKEN_URL = 'http://localhost.baidu.com:7788/ack';
修改为你的实际的服务器的ack接口。 再次部署和访问,就可以在IE低版本下运行3in1.html。
综上所述,用户先用真实的ak、sk在在浏览器中直接上传文件到BOS模式下开始简单测试,然后通过开发和配置“STS临时认证“的方式实现在IE高版本以及其他浏览器下的安全上传,再理解和部署ack接口,实现通过PostObject接口处理IE低版本。部署到线上正式服务的时候,3in1.js会自动根据浏览器来选择STS模式或者ack模式进行上传。