首页 > 其他分享 >AWS 文件预签名URL

AWS 文件预签名URL

时间:2024-04-29 16:00:50浏览次数:29  
标签:return string err URL AWS aws nil 签名 cfg

 

1.《获取STS临时授权凭证》

2.《通过STS Token分片上传文件》

一、相关文档

1.AWS S3预签名URL文档:https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/example_s3_Scenario_PresignedUrl_section.html

AWS S3只针对文件的存储,若想实现阿里云oss通过URL参数对图片进行处理,则需要使用AWS CloudFront。

CloudFront支持图片处理的解决方案:https://www.amazonaws.cn/solutions/technology/app-development/serverless-image-handler/?nc1=h_ls

CloudFront支持图片处理的实施文档:https://aws-gcr-solutions.s3.cn-north-1.amazonaws.com.cn/cn-serverless-image-handler/latest/docs.zh.pdf

CloudFront预签名URL:https://aws-gcr-solutions.s3.cn-north-1.amazonaws.com.cn/cn-serverless-image-handler/latest/docs.zh.pdf

 二、GO示例

配置了CDN,则走CDN预签名;否则,走bucket预签名

package main

import (
    "crypto"
    "crypto/rsa"
    "crypto/sha1"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "errors"
    "fmt"
    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/credentials"
    "github.com/aws/aws-sdk-go-v2/service/s3"
    "strings"
    "time"
    "context"
)

var PrivatePemKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEowI....wQgDKV7BGo
-----END RSA PRIVATE KEY-----`
var KeyPairID = "{keypid}" //AWS控制台PairID
func main() {
    cfg := &StoreClientConf{
        RoleArn:         "{bucket roleArn}",
        Region:          "{bucket region}",
        AccessKeyID:     "{bucket ak}",
        AccessKeySecret: "{bucket sk}",
        CDNDomain: "{cdn 域名}", //通过该参数可控制使用S3的预签名,还是使用CDN预签名
    }
    client := NewAwsClient(cfg)
    objectKey := "aws/20240422104414.png"
    var bucketName = "{bucket name}"
    url, err := client.SignUrl(context.Background(), bucketName, objectKey, 86400, "image/resize,w_200,h_100")
    if err != nil {
        fmt.Println("client.SignUrl err: " + err.Error())
    }
    fmt.Println("sign url: " + url)
}

type AwsClient struct {
    roleArn         string
    region          string
    accessKeyID     string
    accessKeySecret string
    cdnDomain string
}

type StoreClientConf struct {
    RoleArn         string
    Region          string
    AccessKeyID     string
    AccessKeySecret string
    CDNDomain string
}

func NewAwsClient(cfg *StoreClientConf) *AwsClient {
    return &AwsClient{
        roleArn:         cfg.RoleArn,
        region:          cfg.Region,
        accessKeyID:     cfg.AccessKeyID,
        accessKeySecret: cfg.AccessKeySecret,
        cdnDomain: cfg.CDNDomain, //开启了AWS CloudFront CDN,可支持URL参数处理图片
    }
}

func (s *AwsClient) SignUrl(ctx context.Context, bucketName, objectKey string, expire int32, ossProcess string) (string, error) {
    // 判断是走S3的预签名还是走CDN的预签名
    if s.cdnDomain == "" { //S3的文件预签名URL,不支持图片处理
        return s.S3SignUrl(ctx, bucketName, objectKey, expire)
    }
    return s.CDNSignUrl(ctx, objectKey, expire, ossProcess) //AWS CDN预签名,支持URL参数处理图片
}

func (s *AwsClient) CDNSignUrl(ctx context.Context, objectKey string, expire int32, ossProcess string) (string, error) {
    objectKey = strings.TrimLeft(objectKey, "/") //去除最左边的/
    path := "https://" + s.cdnDomain + "/" + objectKey
    if ossProcess != "" {
        path += "?x-oss-process=" + ossProcess
    }
    expires := time.Now().Add(time.Duration(expire) * time.Second).Unix()
    separator := "?"
    if strings.Contains(path, "?") {
        separator = "&"
    }

    policy := fmt.Sprintf(`{"Statement":[{"Resource":"%s","Condition":{"DateLessThan":{"AWS:EpochTime":%d}}}]}`, path, expires)
    signature, err := rsaSHA1Sign(policy)
    if err != nil {
        return "", errors.New("CDNSignUrl rsaSHA1Sign err: " + err.Error())
    }
    signatureEncoded := urlSafeBase64Encode(signature)
    signUrl := fmt.Sprintf("%s%sExpires=%d&Signature=%s&Key-Pair-Id=%s", path, separator, expires, signatureEncoded, KeyPairID)
    return signUrl, nil
}

// https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/example_s3_Scenario_PresignedUrl_section.html
func (s *AwsClient) S3SignUrl(ctx context.Context, bucketName, objectKey string, expire int32) (string, error) {
    // 1.初始化客户端
    cfg, err := s.loadConfig(ctx)
    if err != nil {
        return "", err
    }
    client := s3.NewFromConfig(cfg)
    pClient := s3.NewPresignClient(client)

    // 2.调用s3接口,获取文件预签名URL
    input := &s3.GetObjectInput{
        Bucket: aws.String(bucketName),
        Key:    aws.String(objectKey),
    }
    response, err := pClient.PresignGetObject(ctx, input, func(opts *s3.PresignOptions) {
        opts.Expires = time.Duration(expire) * time.Second
    })
    if err != nil {
        return "", errors.New("SignUrl pClient.PresignGetObject err: "+err.Error())
    }
    if response == nil {
        return "", errors.New("SignUrl response is nil")
    }
    return response.URL, nil
}

func (s *AwsClient) loadConfig(ctx context.Context) (aws.Config, error) {
    cfg, err := config.LoadDefaultConfig(ctx,
        config.WithRegion(s.region),
        config.WithCredentialsProvider(credentials.StaticCredentialsProvider{
            Value: aws.Credentials{
                AccessKeyID: s.accessKeyID, SecretAccessKey: s.accessKeySecret, SessionToken: "",
                Source: "",
            },
        }),
    )
    if err != nil {
        fmt.Println("awsClient LoadDefaultConfig err:" + err.Error())
        return aws.Config{}, errors.New("awsClient LoadDefaultConfig err")
    }

    return cfg, nil
}

func rsaSHA1Sign(policy string) ([]byte, error) {
    // Load the private key
    privateKeyBlock, _ := pem.Decode([]byte(PrivatePemKey))
    privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
    if err != nil {
        return nil, err
    }

    // Compute the signature
    hashed := sha1.Sum([]byte(policy))
    signature, err := rsa.SignPKCS1v15(nil, privateKey, crypto.SHA1, hashed[:]) //
    if err != nil {
        return nil, err
    }

    return signature, nil
}

func urlSafeBase64Encode(value []byte) string {
    encoded := base64.StdEncoding.EncodeToString(value)
    // Replace unsafe characters +, = and / with the safe characters -, _, and ~
    encoded = strings.ReplaceAll(encoded, "+", "-")
    encoded = strings.ReplaceAll(encoded, "=", "_")
    encoded = strings.ReplaceAll(encoded, "/", "~")
    return encoded
}

 

标签:return,string,err,URL,AWS,aws,nil,签名,cfg
From: https://www.cnblogs.com/573583868wuy/p/18165779

相关文章

  • @aws-sdk 支持的库
    abort-controllerbody-checksum-nodechunked-stream-reader-nodeclient-accessanalyzerclient-accountclient-acmclient-acm-pcaclient-alexa-for-businessclient-ampclient-amplifyclient-amplifybackendclient-amplifyuibuilderclient-api-gatewayclient-apiga......
  • vite 项目,背景图报错 The request url "xx/xx/xx.xx" is outside of Vite serving all
    版本vite3.2.6vue3.2.37 背景本地启项目,项目中引用了自研组件库(没有安装,通过文件路径直接引用,便于调试项目和组件),两者文件夹是平级的组件库中背景图:background:100%/100%no-repeaturl('../assets/svg/xxx.svg'); 问题本地启动项目之后,背景图未正常展示浏览器控......
  • PHP 使用CURL库IP欺骗,隐藏真实客户端IP
    首先搭建环境,建立个ip.php.代码如下:<?error_reporting(0);functionGetIP(){if($_SERVER['HTTP_CLIENT_IP']){$onlineip=$_SERVER['HTTP_CLIENT_IP'];}elseif($_SERVER['HTTP_X_FORWARDED_FOR']){$onlineip=$_SERVER['HTTP_X_......
  • 通过AWS STS临时授权凭证分片上传文件
    一、相关文档1.AWS分片上传文档:https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/mpuoverview.html2.获取AWS STS临时授权凭证,go示例二、GO示例packagemainimport("context""errors""fmt""github.com/aws/aws-sdk-go-v2/......
  • Jmeter设置签名
    一、背景:接口请求时一般都需要设置签名,没有签名,接口是无法请求成功的签名规则:MD5(秘钥+时间戳+业务参数),然后转大写字母!示例:转大写(MD5(appsecret+timestemp+param))二、jmeter设置签名jmeter设置签名是在beanshell里面设置的,具体代码如下importorg.apache.commo......
  • iOS 隐私清单和SDK签名
    隐私清单:<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEplistPUBLIC"-//Apple//DTDPLIST1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plistversion="1.0"><dict><!--......
  • curl wget 下载文件
    curl下载文件:curl-kOhttps://10.0.8.5:8888/chfs/shared/Application/360se13.1.6055.0.exe#下载远程服务器上的文件,需要定位到末端文件-k#忽略服务器ssl证书-O#保存文件至本地,并使用源文件名-ozhang.exe#使用自定义文件名zhang.exe保存......
  • keycloak~RequiredActionProvider中获取表单认证前URL的参数
    在keycloak中,我们在进行brower浏览器的表单认证时,一般在跳到本页面时,URL上会有redirect_uri这种参数,用来告诉keycloak,在认证成功后的跳转地址,你在表单认证控制器中,可以通过context.getHttpRequest().getUri().getQueryParameters().getFirst("redirect_uri")进行获取,而当你为browe......
  • Python3.8.4 解决 ImportError: urllib3 v2 only supports OpenSSL 1.1.1+, currently
    系统版本:CentOSLinuxrelease7.6.1810(Core)编译安装Python3.8.4[root@hankyoon~]#tar-xvfPython-3.8.4.tgz[root@hankyoon~]#cdPython-3.8.4/[root@hankyoon~]#./configure--prefix=/usr/local/python3.8[root@hankyoon~]#make&&makeinstall[......
  • AWS S3 Lambda Python脚本函数执行时报错AttributeError: module ‘PIL‘ has no attr
    背景代码示例如下importPILdefadd_image(self,tag,img,step):summary=Summary()bio=BytesIO()iftype(img)==str:img=PIL.Image.open(img)eliftype(img)==PIL.Image.Image:passelse:img=scipy.misc.......