sts.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // 临时密钥服务例子
  2. var bodyParser = require('body-parser');
  3. var STS = require('qcloud-cos-sts');
  4. var express = require('express');
  5. var crypto = require('crypto');
  6. var pathLib = require('path');
  7. var fs = require('fs');
  8. // 配置参数
  9. var config = {
  10. secretId: process.env.SecretId,
  11. secretKey: process.env.SecretKey,
  12. proxy: process.env.Proxy,
  13. durationSeconds: 1800,
  14. bucket: process.env.Bucket,
  15. region: process.env.Region,
  16. allowPrefix: '_ALLOW_DIR_/*',
  17. // 密钥的权限列表
  18. allowActions: [
  19. // 所有 action 请看文档 https://cloud.tencent.com/document/product/436/31923
  20. // 简单上传
  21. 'name/cos:PutObject',
  22. 'name/cos:PostObject',
  23. // 分片上传
  24. 'name/cos:InitiateMultipartUpload',
  25. 'name/cos:ListMultipartUploads',
  26. 'name/cos:ListParts',
  27. 'name/cos:UploadPart',
  28. 'name/cos:CompleteMultipartUpload'
  29. ],
  30. };
  31. // 创建临时密钥服务和用于调试的静态服务
  32. var app = express();
  33. var replaceBucketRegion = (filePath) => {
  34. return (req, res, next) => {
  35. var content = fs.readFileSync(filePath).toString()
  36. .replace(/(var config = {\r?\n *Bucket: ')test-1250000000(',\r?\n *Region: ')ap-guangzhou(',?\r?\n};?)/,
  37. '$1' + process.env.Bucket + '$2' + process.env.Region +'$3');
  38. res.header('Content-Type', 'application/javascript');
  39. res.send(content);
  40. };
  41. };
  42. app.use('/demo/demo.js', replaceBucketRegion(pathLib.resolve(__dirname, '../demo/demo.js')));
  43. app.use('/test/test.js', replaceBucketRegion(pathLib.resolve(__dirname, '../test/test.js')));
  44. app.use('/dist/', express.static(pathLib.resolve(__dirname, '../dist')));
  45. app.use('/demo/', express.static(pathLib.resolve(__dirname, '../demo')));
  46. app.use('/test/', express.static(pathLib.resolve(__dirname, '../test')));
  47. app.all('/', (req, res, next) => res.redirect('/demo/'));
  48. app.use(bodyParser.json());
  49. // 格式一:临时密钥接口
  50. app.all('/sts', function (req, res, next) {
  51. // TODO 这里根据自己业务需要做好放行判断
  52. if (config.allowPrefix === '_ALLOW_DIR_/*') {
  53. res.send({error: '请修改 allowPrefix 配置项,指定允许上传的路径前缀'});
  54. return;
  55. }
  56. // 获取临时密钥
  57. var LongBucketName = config.bucket;
  58. var ShortBucketName = LongBucketName.substr(0, LongBucketName.indexOf('-'));
  59. var AppId = LongBucketName.substr(LongBucketName.indexOf('-') + 1);
  60. var policy = {
  61. 'version': '2.0',
  62. 'statement': [{
  63. 'action': config.allowActions,
  64. 'effect': 'allow',
  65. 'resource': [
  66. 'qcs::cos:' + config.region + ':uid/' + AppId + ':prefix//' + AppId + '/' + ShortBucketName + '/' + config.allowPrefix,
  67. ],
  68. }],
  69. };
  70. var startTime = Math.round(Date.now() / 1000);
  71. STS.getCredential({
  72. secretId: config.secretId,
  73. secretKey: config.secretKey,
  74. proxy: config.proxy,
  75. region: config.region,
  76. durationSeconds: config.durationSeconds,
  77. policy: policy,
  78. }, function (err, tempKeys) {
  79. if (tempKeys) tempKeys.startTime = startTime;
  80. res.send(err || tempKeys);
  81. });
  82. });
  83. // // 格式二:临时密钥接口,支持细粒度权限控制
  84. // // 判断是否允许获取密钥
  85. // var allowScope = function (scope) {
  86. // var allow = (scope || []).every(function (item) {
  87. // return config.allowActions.includes(item.action) &&
  88. // item.bucket === config.bucket &&
  89. // item.region === config.region &&
  90. // (item.prefix || '').startsWith(config.allowPrefix);
  91. // });
  92. // return allow;
  93. // };
  94. // app.all('/sts-scope', function (req, res, next) {
  95. // var scope = req.body;
  96. //
  97. // // TODO 这里根据自己业务需要做好放行判断
  98. // if (config.allowPrefix === '_ALLOW_DIR_/*') {
  99. // res.send({error: '请修改 allowPrefix 配置项,指定允许上传的路径前缀'});
  100. // return;
  101. // }
  102. // // TODO 这里可以判断 scope 细粒度控制权限
  103. // if (!scope || !scope.length || !allowScope(scope)) return res.send({error: 'deny'});
  104. //
  105. // // 获取临时密钥
  106. // var policy = STS.getPolicy(scope);
  107. // var startTime = Math.round(Date.now() / 1000);
  108. // STS.getCredential({
  109. // secretId: config.secretId,
  110. // secretKey: config.secretKey,
  111. // proxy: config.proxy,
  112. // durationSeconds: config.durationSeconds,
  113. // policy: policy,
  114. // }, function (err, tempKeys) {
  115. // if (tempKeys) tempKeys.startTime = startTime;
  116. // res.send(err || tempKeys);
  117. // });
  118. // });
  119. //
  120. // // 用于 PostObject 签名保护
  121. // app.all('/post-policy', function (req, res, next) {
  122. // var query = req.query;
  123. // var now = Math.round(Date.now() / 1000);
  124. // var exp = now + 900;
  125. // var qKeyTime = now + ';' + exp;
  126. // var qSignAlgorithm = 'sha1';
  127. // var policy = JSON.stringify({
  128. // 'expiration': new Date(exp * 1000).toISOString(),
  129. // 'conditions': [
  130. // // {'acl': query.ACL},
  131. // // ['starts-with', '$Content-Type', 'image/'],
  132. // // ['starts-with', '$success_action_redirect', redirectUrl],
  133. // // ['eq', '$x-cos-server-side-encryption', 'AES256'],
  134. // {'q-sign-algorithm': qSignAlgorithm},
  135. // {'q-ak': config.secretId},
  136. // {'q-sign-time': qKeyTime},
  137. // {'bucket': config.bucket},
  138. // {'key': query.key},
  139. // ]
  140. // });
  141. //
  142. // // 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
  143. // // 步骤一:生成 SignKey
  144. // var signKey = crypto.createHmac('sha1', config.secretKey).update(qKeyTime).digest('hex');
  145. //
  146. // // 步骤二:生成 StringToSign
  147. // var stringToSign = crypto.createHash('sha1').update(policy).digest('hex');
  148. //
  149. // // 步骤三:生成 Signature
  150. // var qSignature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex');
  151. //
  152. // console.log(policy);
  153. // res.send({
  154. // policyObj: JSON.parse(policy),
  155. // policy: Buffer.from(policy).toString('base64'),
  156. // qSignAlgorithm: qSignAlgorithm,
  157. // qAk: config.secretId,
  158. // qKeyTime: qKeyTime,
  159. // qSignature: qSignature,
  160. // // securityToken: securityToken, // 如果使用临时密钥,要返回在这个资源 sessionToken 的值
  161. // });
  162. // });
  163. //
  164. app.all('*', function (req, res, next) {
  165. res.send({code: -1, message: '404 Not Found'});
  166. });
  167. // 启动签名服务
  168. app.listen(3000);
  169. console.log('app is listening at http://127.0.0.1:3000');