Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

我采用浏览器直接上传到oss, oss回调应用服务器有没有node.je 版本的。 #85

Closed
mrlong opened this issue Mar 23, 2016 · 12 comments

Comments

@mrlong
Copy link

mrlong commented Mar 23, 2016

https://help.aliyun.com/document_detail/oss/practice/pc_web_upload/js_php_callback.html?spm=5176.docoss/practice/post_object_callback.2.3.nN7GWD

<?php
// 1.获取OSS的签名header和公钥url header
$authorizationBase64 = "";
$pubKeyUrlBase64 = "";
/*
 * 注意:如果要使用HTTP_AUTHORIZATION头,你需要先在apache或者nginx中设置rewrite,以apache为例,修改
 * 配置文件/etc/httpd/conf/httpd.conf(以你的apache安装路径为准),在DirectoryIndex index.php这行下面增加以下两行
    RewriteEngine On
    RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
 * */
if (isset($_SERVER['HTTP_AUTHORIZATION']))
{
    $authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION'];
}
if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL']))
{
    $pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL'];
}

if ($authorizationBase64 == '' || $pubKeyUrlBase64 == '')
{
    header("http/1.1 403 Forbidden");
    exit();
}

// 2.获取OSS的签名
$authorization = base64_decode($authorizationBase64);

// 3.获取公钥
$pubKeyUrl = base64_decode($pubKeyUrlBase64);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $pubKeyUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$pubKey = curl_exec($ch);
if ($pubKey == "")
{
    //header("http/1.1 403 Forbidden");
    exit();
}

// 4.获取回调body
$body = file_get_contents('php://input');

// 5.拼接待签名字符串
$authStr = '';
$path = $_SERVER['REQUEST_URI'];
$pos = strpos($path, '?');
if ($pos === false)
{
    $authStr = urldecode($path)."\n".$body;
}
else
{
    $authStr = urldecode(substr($path, 0, $pos)).substr($path, $pos, strlen($path) - $pos)."\n".$body;
}

// 6.验证签名
$ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5);
if ($ok == 1)
{
    header("Content-Type: application/json");
    $data = array("Status"=>"Ok");
    echo json_encode($data);
}
else
{
    //header("http/1.1 403 Forbidden");
    exit();
}

?>


@mrlong
Copy link
Author

mrlong commented Mar 23, 2016

上面的代码能否转成js 版本。

@rockuw
Copy link
Collaborator

rockuw commented Mar 24, 2016

@mrlong 我会在后续的版本中增加对oss callback的支持。

@wendycan
Copy link

现在浏览器往 OSS 发请求的时候怎么设置 callback url ? @rockuw

@rockuw
Copy link
Collaborator

rockuw commented Apr 20, 2016

@wendycan 现在只能根据文档:https://help.aliyun.com/document_detail/oss/api-reference/object/Callback.html ,手动构造好x-oss-callback,然后在调用api的时候在headers中指定:

client.multipartUpload(storeAs, file, {
  headers: {
    'x-oss-callback': callback
  }
}).then(function (result) {
  console.log(result);
}).catch(function (err) {
  console.log(err);
});

@wendycan
Copy link

wendycan commented Apr 20, 2016

@rockuw 可以通过 url 带参数吗,还有就是我本来用 aliyun-sdk-js 的,但是没有找到设置 headers 的文档。aliyun-sdk-js 在哪里可以设置 headers ?

@rockuw
Copy link
Collaborator

rockuw commented Apr 20, 2016

带什么参数?x-oss-callback只能在header中。

@wendycan
Copy link

wendycan commented Apr 21, 2016

@rockuw 我看到 文档 里介绍有三种方式来设置回调:

  • 在URL中携带参数。
  • 在Header中携带参数。
  • 在POST请求的body中使用表单域来携带参数,在使用POST请求上传Object的时候只能使用这种方式来指定回调参数。

第一种不可以吗?

@rockuw
Copy link
Collaborator

rockuw commented Apr 21, 2016

@wendycan

  1. URL中设置callback,但是签名在header中,这个目前js sdk不能支持。因为它会把callback当作一个query parameter而没有加到签名中;
  2. aliyun-sdk-js的问题你只能看一下代码,或者在那个repo里开issue

@wendycan
Copy link

wendycan commented Apr 21, 2016

@rockuw 非常感谢了

@Gzzzy
Copy link

Gzzzy commented Jan 31, 2018

@rockuw

callback出了java、python、php等等的demo,有没有node版本的
自己对着别的版本的代码改出来的不好使

@LKCheng
Copy link

LKCheng commented Jan 22, 2019

我也在找node版本的~怎么就没有呢

@undefinedZNN
Copy link

undefinedZNN commented Jul 16, 2020

aliyun-oss 的确是对nodejs 不够友好,找了好久终于找到解决方案了分享给大家

const crypto = require('crypto');
// 1.获取OSS的签名
// 例子 "Lw8CsG8j3iNCzQliYUxmCKuOiJzsPsPf86xkEqQmSNcZB6mccM0m5KqH5yXOPvreP6w37IHxzMqdjN4nLy0URw=="
const signatureBase64 = ctx.request.header.authorization;
// 2.获取公钥
// 例子 "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKs/JBGzwUB2aVht4crBx3oIPBLNsjGs\nC0fTXv+nvlmklvkcolvpvXLTjaxUHR3W9LXxQ2EHXAJfCB+6H2YF1k8CAwEAAQ==\n-----END PUBLIC KEY-----\n"
const pubKeyUrl = Buffer.from(ctx.request.header['x-oss-pub-key-url'], 'base64').toString();
const pubKeyRes = await axios.get(pubKeyUrl);
const pubKey = pubKeyRes.data;

// 3 获取待签名字符串
// 例子 '/oss/callback\n{"tradeNo":"202007151283383770610798592","mime":"image/png","size":848409,"objectName":"local/upload/image/f2fb68c0c69911ea9b8367206d92f50d"}'
 const authStr = decodeURI(path) + queryString + '\n' + body;

// 验签
const verifier = crypto.createVerify('md5WithRSAEncryption');
verifier.update(Buffer.from(authStr));
verifier.verify(pubKey, authorizationBase64, 'base64');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants