登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> SoftHub关联区 >> 主题: oss的跨域名访问和第三方临时授权上传[带总结]     [回主站]     [分站链接]
oss的跨域名访问和第三方临时授权上传[带总结]
clq
浏览(317) - 2019-03-02 16:33:56 发表 编辑

关键字: oss

[2020-06-29 13:01:14 最后更新]
oss的跨域名访问和第三方临时授权上传

阿里云做得挺好的,但在这一块上实在不怎么样。特别是文档写得非常的零散,我都综合了好多文章再加上网友的,再加上各种鼓捣最终才弄好了。
而且这其中还有很多隐藏的坑。前前后后居然花了一两个月!但实际上出来的代码非常少,仅仅几行就解决了。可见阿里云的文档之差。
在这期间我还极度诧异的发现各个语言 sdk 在这上面的接口居然是不一样的!

对于 js 上传一定要设置跨域,同时还要允许全部头信息  -- 没有一个文档提到。我参考的是这篇搜索到的文档
https://help.aliyun.com/knowledge_detail/39518.html


更新,发现一个文档提到大部分,不过对要开放的响应头仍然是漏掉了断点续传需要的头信息。
https://help.aliyun.com/document_detail/64056.html

应该至少是
etag
x-oss-request-id

-------------------------------------
临时授权真的做得烂。这里有个很牛B的缩写 arn 。用在 roleArn 中。我用了好几年一直没查到 arn 的完整英文单词是什么,所以也一直不明白 roleArn 到底指的是什么。
今天偶然看到 https://yq.aliyun.com/articles/756616 说是 “(Aliyun Resource Name,简称ARN)”的意思,就是说阿里专有的对一个东西的命名标识的意思。......
这阿里的开发恐怕是个自恋狂吧。神经病。

说实在的,正常一点的开发都会命名为 roleID 吧。真是白痴。浪费大家的时间。

-------------------------------------
//1.要有一个可以使用角色的账号。不能是普通账号。
普通账号是有全部权限的 AccessKey,而这个是 RAM 用户名对应的 AccessKey 。而 RAM 用户名完全无用,和 role 角色名一样,都没用,实际上用的是它们的 ID 。
//2.要给这个账号一个角色。并得到角色的 "资源描述符"
//3.不要给角色太多权限,自己写访问规则最好。没有规则的情况下,角色会得到角色默认的所有权限。
//4.还要设置 bucket 的跨域设置。否则会报 403 Forbidden 。如果是断点还要设置“暴露 Headers” (而且还不能是*)
//
//策略 -- policy - 政策
//role -- 角色
//arn -- RAM角色的全局资源描述符(Role ARN)Role ARN是角色的全局资源描述符(Aliyun Resource Name,简称ARN),用来指定具体角色

好了,根据以上三个东西可以得到一个临时 AccessKey 。可以像普通 oss 一样用了。 .... 还要在请求中加入令牌字符串。
令牌字符串是在得到临时 AccessKey 时得到的。所以说是后面操作就和普通的一样了其实是不对的,一定要多加一个字段。



clq  2019-03-02 16:35:00 发表 编辑

[图片]

这是非常关键的,非常与众不同的设置步骤 ... 唉 看仔细了.



clq  2019-03-02 16:45:05 发表 编辑


同时为了方便我使用的是 js 测试,意外的发现其实不用装 node.js 直接在一个页面中就能方便的完成。原因是 node.js 的其实可以在浏览器中直接使用! 看了阿里的文档确实说了浏览器端是从 node 来的。但... 有人告诉我可以通用的话我能省不知道多少时间啊。

其实最关键的其实说出来能省两个月的时间:那就是在访问地址中加入临时的授权签名即可,相关 sdk 内容非常多,其实看
https://help.aliyun.com/document_detail/31952.html

就好了,但这里仍然没有完整的授权签名例子,只是签名的例子 ... 唉。

"
OSS SDK中提供了提供URL签名的方法,使用方法请参看SDK参考中的授权访问文档。
OSS SDK的URL签名实现,请参看下表:
SDK    URL签名方法    实现文件
Java SDK    OSSClient.generatePresignedUrl    OSSClient.java

Python SDK    Bucket.sign_url    api.py

.Net SDK    OssClient.GeneratePresignedUri    OssClient.cs

PHP SDK    OssClient.signUrl    OssClient.php

JavaScript SDK    signatureUrl    Object.js

C SDK    oss_gen_signed_url    oss_object.c
"

另外在 https://helpcdn.aliyun.com/knowledge_detail/39543.html 还有些示例代码
--------------------------------------------------

OSS如何通过sdk获取object的签名URL

更新时间:2017-06-07 13:26:11

 

1)  Javasdk:

   Date expiration = new Date(new Date().getTime() + 3600 * 1000);// 生成URL
   URL url = client.generatePresignedUrl(bucketName, key, expiration);

2)Phpsdk:

    $signedUrl = $ossClient->signUrl($bucket, $object, $timeout);

3)Pythonsdk:在URL中实现签名,必须至少包含Signature,Expires,OSSAccessKeyId三个参数

     h = hmac.new("OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV",

             "GET\n\n\n1141889120\n/oss-example/oss-api.pdf",

             sha)

     urllib.quote_plus (base64.encodestring(h.digest()).strip())

 

或者

   auth = oss2.Auth('您的AccessKeyId', '您的AccessKeySecret')
   bucket = oss2.Bucket(auth, '您的Endpoint', '您的Bucket名')
   print(bucket.sign_url('GET', 'object-in-bucket.txt', 60))

4)Androidsdk:

    String url = oss.presignConstrainedObjectURL("<bucketName>", "<objectKey>", 30 * 60);

5) IOSsdk:

    NSString * constrainURL = nil;// sign constrain url

    OSSTask * task = [client presignConstrainURLWithBucketName:@"<bucket name>"
                                            withObjectKey:@"<object key>"
                                   withExpirationInterval: 30 * 60];

     if (!task.error) {
          constrainURL = task.result;
       } else {   

           NSLog(@"error: %@", task.error);
       }

6)  osscmd:

signurl(sign) oss://bucket/object --timeout=[timeout_seconds]

SDK的具体代码可以参考如下链接:http://docs.aliyun.com/?spm=5176.383338.201.62.MwuAaz#/oss/sdk/java-sdk&preface



clq  2019-03-02 16:47:32 发表 编辑

另外,用浏览器测试的话你会发现其实调用了两次请求 OPTIONS请求和GET请求

据说是浏览器要先用 options 先判断服务器是否支持跨域 ... 浏览器其实也够无聊的...

clq  2019-03-02 16:50:45 发表 编辑

还需要知道自己的 endpoint 可参考
https://mvp.aliyun.com/zhidao/2061

不过实际上是支持 https 的,方法是直接加上 "https://" 象这样 endpoint = "https://oss-cn-shanghai.aliyuncs.com";//上海

clq  2019-03-02 16:52:03 发表 编辑

js 的 sdk 下载下来后有一大堆文件,其实只要引入一个就好了。例如

<script src="./ali-oss/dist/aliyun-oss-sdk.min.js"></script>

方法来自 https://help.aliyun.com/document_detail/64041.html
居然在 github 其源码中没有这些说明。

clq  2019-03-02 16:54:16 发表 编辑

完整各个语言的 sdk 在此 https://help.aliyun.com/document_detail/52834.html

clq  2019-03-02 17:02:47 发表 编辑

我主要参考
https://blog.csdn.net/violentbomb/article/details/82257973
https://blog.csdn.net/u012957549/article/details/77986463

特别是前一篇中的代码。唉,比官方文档简单多了。
--------------------------------------------------
基于临时授权方式的OSS上传
2018年08月31日 16:07:55 躁动de气球 阅读数:279更多
个人分类: 杂项 JavaScript
基于临时授权方式的OSS上传
OSS支持临时授权URL,可以实现临时性的上传和下载,此处介绍一下如何在项目中使用。
对应场景:客户端需要上传文件,但不想或不方便将accessKeyId和accessKeySecret下发到客户端,或者无法继承OSS-SDK的情况。
具体上传仍旧是客户端与OSS服务器之间直接进行.
应用的理论核心是OSS提供的”在URL中包含签名”,参考这里
实现思路:
客户端客户端业务服务器业务服务器OSS服务器OSS服务器[A]获取用于上传的临时URL[B]调用OSS-SDK生成临时URL[C]返回临时URL[D]使用临时URL上传文件[E]返回上传结果
代码实现
?    [A] 客户端向业务服务器发送获取上传地址的请求,一般是POST请求,向服务器发送要上传的文件信息(如文件名)
?    [B] 业务服务器收到对应请求后对用户身份做验证,通过后调用OSS-SDK或者手动生成对应的临时URL.
NodeJS下可以用以下代码生成: (业务服务器端)
var client = new OSS({
    endpoint: configInfo.OSS_ENDPOINT,
    accessKeyId: configInfo.OSS_KEY,
    accessKeySecret: configInfo.OSS_SECERT,
    bucket: configInfo.OSS_BUCKET
});
function getTempSignedUrl(ossObjectPath,type){
  var url = client.signatureUrl(ossObjectPath, {
    expires: 60, //过期时间,这里设置为短期的60s
    method: 'PUT', //由于是上传,此处填写PUT; 如果是下载的话,为GET
    'content-type': type||'application/octet-stream' //conent类型,默认为octet-stream
  });
  console.log(url);
  return url;
}

?    [C] 业务服务器将生成好的url返回客户端,也就是刚刚的POST请求的响应.
?    [D] 客户端根据临时URL进行上传
web浏览器里面可以使用下面代码实现上传:(浏览器端)
function putfileToOSS(url, domId, contentType) {
        var f = document.getElementById(domId); //input file控件
        var uploadReq = new Request(url, { //url为服务器接口URL
            method: "PUT",
            headers: new Headers({ 'Content-Type': contentType||'application/octet-stream' }),
            body: f.files[0]  //仅支持单个文件,取第一个
        });
        return fetch(uploadReq).then(x => x.text()).then(x => {
            console.log(x); //此处假定响应信息是text
            return x;
        });
    }

?    [E] OSS服务器返回上传结果,200为成功,其他为失败,常见的有403(过期或权限有误)等,具体信息参考OSS相关文档.
风险
临时URL有被泄露的可能性,请注意在业务层面做好安全保障,避免无意或有意泄露.
同样,临时URL的有效期不宜太长,时间过长该风险会变大.
可以通过制定content-type的方式进一步减少该风险.
待改进
要求更严格的情况下,可以在上述功能的基础上增加文件MD5的传递,也就是根据待上传文件的MD5生成临时URL,这样会对客户端有一定的要求,但安全性更高.(此种方案OSS支持)



clq  2019-03-02 17:04:16 发表 编辑

https://blog.csdn.net/lsq_401/article/details/83148349

阿里云OSS上传、下载和生成临时url授权第三方上传操作
2018年10月18日 16:12:18 慕安凉 阅读数:975
阿里云OSS的基础配置
    private static String accessKeyId = "";
    private static String accessKeySecret = "";
    private static String bucketName = "";
    private static String endpoint = "https://oss-cn-shanghai.aliyuncs.com";//上海
    private static String folder = "";//目录
初始化:OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
jar包:"com.aliyun.oss:aliyun-sdk-oss:2.8.3",
1、文件上传
    ......
    byte[] bytes =
    ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
    String fileName = "file.jpg";
    PutObjectResult putObjectResult = ossClient.putObject(bucketName,folder+fileName,bais);
    putObjectResult.getETag();上传成功后会返回MD5值
2、生成临时授权的URL,第三方可以用这个URL进行上传操作
Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 180);//设置该URL的有效期180天
    GeneratePresignedUrlRequest request =
                    new GeneratePresignedUrlRequest(bucketName, folder+urlRequest.getFileName(), HttpMethod.PUT);//设置为这个URL只支持PUT操作
    request.setExpiration(expiration);
    request.setContentType("application/octet-stream");
    URL url = ossClient.generatePresignedUrl(request);
   
    说起ContentType,这个我是爬了好久的坑,按照官网的提供的ContentType对应值(https://helpcdn.aliyun.com/knowledge_detail/39522.html),
    我试了一下(video/mpeg4)这个类型,可以上传成功,也可以下载成功,就是没法播放,总是提醒文件损坏了。
    最后改成(application/octet-stream),既可以上传成功,下载下来也可以播放,试了一下图片,依然正常,索性就用这个了,感觉这个类型是万能的
3、根据生成的临时授权URL进行文件上传
Request中video的类型为:MultipartFile
   
    HttpClient httpClient = HttpClients.createDefault();
    HttpResponse response;
    HttpPut put = new HttpPut(ossRequest.getUrl());
    HttpEntity reqEntity = EntityBuilder.create().setBinary(request.getVideo().getBytes()).build();
    put.setEntity(reqEntity);
    response = httpClient.execute(put);
    HttpEntity resEntity=response.getEntity();
   
    PS:当时按照网上教程给HttpPut也设置ContentType:put.addHeader("Content-Type", "application/octet-stream");
       上传成功下载下来就是没法播放,去掉之后就好了,也不知道是我添加姿势不对,还是什么原因
4、生成下载链接
    Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 180);
    URL url = ossClient.generatePresignedUrl(bucketName, folder+urlRequest.getFileName(), expiration);
5、获取bucket下某个目录下的所有文件的key
    ObjectListing objectListing = ossClient.listObjects(bucketName,folder);
    List<OSSObjectSummary> ossList = objectListing.getObjectSummaries();
    List<String> list = new ArrayList<>();
    for (OSSObjectSummary s : ossList) {
         list.add(s.getKey());
    }
6、删除文件
ossClient.deleteObject(bucketName, folder+fileName());


clq  2019-03-02 17:08:38 发表 编辑

最后我自己写的最简单,如下:

<html>

<head>

<script src="./ali-oss/dist/aliyun-oss-sdk.min.js"></script>

</head>

<body>
   
<script>
   
//代码参考 https://blog.csdn.net/violentbomb/article/details/82257973 //文中的 node.js 端代码可以原封不动的在浏览器上通过
//sdk 参考 https://help.aliyun.com/document_detail/31952.html?spm=a2c4g.11186623.6.1014.6f0820beuCgqaj
//https://help.aliyun.com/document_detail/52834.html?spm=a2c4g.11186623.3.2.49bcc06dkUHdsO
//https://help.aliyun.com/document_detail/64041.html?spm=a2c4g.11186623.2.15.667f5d26uptCYJ#concept-64041-zh
   
//var OSS_ENDPOINT = "oss-cn-hangzhou.aliyuncs.com";
//private static String endpoint = "https://oss-cn-shanghai.aliyuncs.com";//上海
var OSS_ENDPOINT = "oss-cn-hangzhou.aliyuncs.com"; //"https://oss-cn-hangzhou.aliyuncs.com";
//奇怪,老是报//The request signature we calculated does not match the signature you provided. Check your key and signing method.
var OSS_KEY = "....oss的访问id,一个用户可以自己生成很多个...";
var OSS_SECERT = "....访问id 对应的那个访问字符串..";
var OSS_BUCKET = "你的oss库名称,一个账号下是可以建立多个的,就是你的访问域名最前面的那一个";
       
var client = new OSS({
    endpoint: OSS_ENDPOINT,
    accessKeyId: OSS_KEY,
    accessKeySecret: OSS_SECERT,
    bucket: OSS_BUCKET
});

//对于 oss 本地上传到 oss 中会有个跨域的限制。除了按一般网页的设置好后还要设置 https://help.aliyun.com/knowledge_detail/39518.html
//中所说的 "CORS设置都正确的话,那就检查AllowedHeader的设置,一般建议设置为*"
//同时对于 get 请求可以不设置 method: 'GET' 这样的,但是对于上传时的,是一定要设置为 method: 'PUT' 的,否则 oss 的签名会不通过

function getTempSignedUrl(ossObjectPath,type){
  var url = client.signatureUrl(ossObjectPath, {
    //expires: 60, //过期时间,这里设置为短期的60s
    expires: 60*60, //过期时间,这里设置为短期的60s
    method: 'PUT', //由于是上传,此处填写PUT; 如果是下载的话,为GET
    //method: 'GET', //由于是上传,此处填写PUT; 如果是下载的话,为GET
    //'content-type': type||'application/octet-stream' //conent类型,默认为octet-stream
  });
 
  console.log(url);
 
  document.write("<p>我的第一段 JavaScript</p>");
  document.write(url);
 
  return url;

}//

//--------------------------------------------------
//上传函数
function putfileToOSS(url, domId, contentType) {
    var f = document.getElementById(domId); //input file控件
    var uploadReq = new Request(url, { //url为服务器接口URL
        method: "PUT",
        headers: new Headers({ 'Content-Type': contentType||'application/octet-stream' }),
        //body: f.files[0]  //仅支持单个文件,取第一个
        //mode: "no-cors", //put 请求不支持这样跨域,另外这个只是说不跨域名,其实一点作用没有
        body: "aaabbbccc"  //仅支持单个文件,取第一个
    });
    ///*
    return fetch(uploadReq).then(x => x.text()).then(x => {
        console.log(x); //此处假定响应信息是text
        return x;
    });
    //*/
}//

//--------------------------------------------------

var url1 = getTempSignedUrl("1.txt", "application/octet-stream");



</script>

<input type="file" name="f1" id="f1" value="" />

<input type="button" name="up1" id="up1" value="上传测试" onclick="alert(url1)" />
<br />
<input type="button" name="up2" id="up2" value="上传测试2" onclick="putfileToOSS(url1, f1, 'application/octet-stream')" />

</body>
</html>
//--------------------------------------------------
//2019.05.11 修正一下一个引起 403 signature 错误的地方
就是在签名 content-type 部分加与不加影响很大,PUT 是一定要加,GET 时则是不加的
所以上面的代码中 getTempSignedUrl, new Request 那里要打开那个注释,大概是我后来为了测试 GET 注释的吧。


clq  2019-03-02 17:10:50 发表 编辑

[图片]

最后再上一上关键点。



总数:12 页次:1/2 首页 下一页  >>  尾页  
总数:12 页次:1/2 首页 下一页  >>  尾页  


所在合集/目录
oss 上传文件 更多
跨域全记录 更多



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1