Amazon S3 + CloudFront 数据存储及CDN分发 实践备忘

对于前期用户量不大但是需要稳定服务的项目,S3和Cloudfront是个不错的选择

一,申请amazon 账户 申请过程不再介绍 我是在淘宝上买一张1美元的万事达卡来申请的,成本10块钱左右

1.1,等待申请通过后进入控制台 在所有服务中找到存储 ->s3 (如下图1)如果amazon账号申请已经通过 进入页面就可以直接在页面创建存储桶,我是需要通过编程的方式上传文件,所以这里不再介绍在页面创建存储桶的过程,可以自己玩玩摸索一下

图1
图一
​​​​​

1.2,通过java编程的方式上传文件到存储桶,需要使用到开源包jets3t,maven引入的方式如下

<!-- https://mvnrepository.com/artifact/net.java.dev.jets3t/jets3t -->
        <dependency>
            <groupId>net.java.dev.jets3t</groupId>
            <artifactId>jets3t</artifactId>
            <version>0.9.4</version>
        </dependency>

1.2.1,要通过java访问s3存储桶并进行操作的话,必须要有授权,这个授权需要 AWS_ACCESS_KEY和AWS_SECRET_KEY,这两个key有多种方式获取,最简单粗暴的就是直接在amazon IAM页面去生成一个,申请链接 获取访问Amazon S3的access_key及secret_key 如下图2

图2

1.2.2,获取访问授权的另一种方式(与1.2.1作用相同,都是为了获取对s3访问的凭证,1.2.1和1.2.2可以自己选择用哪种方式)

进入IAM控制台 如下图3 这里相当于建立了amazon的子账户,可以设置这些子账户的访问权限,比如你可以建一个账户只能对s3进行操作,你拿到这个子账户的授权key就只能在代码里访问或者操作s3的资源内容

图3

1.2.3 创建用户 如图4

图4

1.2.4 创建成功后会给你一个秘钥,这个秘钥就是访问s3的凭证

用户秘钥

1.2.5 当然,要为用户添加访问s3的权限,如图5

图5

 

 

1.2.6 获取到的access_key和secret_key后即可对s3进行编程上传文件和获取文件访问地址,java代码片段如下

private static String AWS_ACCESS_KEY = "AKIAINA*******SD3QQ";
private static String AWS_SECRET_KEY = "5WTDmwn***************7JfQd2g5LSs9/t";

要进行s3访问需要首先获取RestS3Service对象

@Override
public S3Service getS3Service(String accKey, String sec_key) {
    AWSCredentials awsCredentials = new AWSCredentials(accKey, sec_key);
    return new RestS3Service(awsCredentials);
}

对s3做一些简单的操作,如创建存储桶,获取存储桶

/**
     * 创建存储桶
     *
     * @param bucketName
     * @param location
     * @return
     */
    @Override
    public S3Bucket createS3Bucket(String bucketName, String location) {
        S3Bucket euBucket = null;
        try {
            euBucket = s3Service.createBucket(bucketName, location);
        } catch (S3ServiceException e) {
            e.printStackTrace();
        }
        return euBucket;
    }

    /**
     * 获取存储桶
     *
     * @param bucketName
     * @param location
     * @return
     */
    @Override
    public S3Bucket getS3Bucket(String bucketName, String location) {
        S3Bucket euBucket = null;
        try {
            euBucket = s3Service.getOrCreateBucket(bucketName, location);
        } catch (S3ServiceException e) {
            e.printStackTrace();
        }
        return euBucket;
    }

1.2.7 上传文件到存储桶(注意此时上传到存储桶中的文件的访问不是公开的,所以此时直接访问可能会出现拒绝访问)

/**
     * 上传本地文件到s3存储桶
     * @param filePath
     * @param s3Service
     * @param euBucket
     * @return
     */
    @Override
    public S3Object localUpload(String filePath, S3Service s3Service, S3Bucket euBucket) {
        File fileData = new File(filePath);
        S3Object fileObject = null;
        try {
            fileObject = new S3Object(fileData);
            fileObject.setKey(UUID.randomUUID().toString().replaceAll("-", ""));
            fileObject = s3Service.putObject(euBucket, fileObject);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileObject;
    }


/**
     * 上传网络文件到s3存储桶
     *
     * @param file
     * @param bucketName
     * @param key
     * @param location
     * @return
     */
    @Override
    public S3Object uploadFileToS3(File file, String bucketName, String key, String location) {
        if (!file.exists()) {
            return null;
        }
        S3Bucket euBucket = getS3Bucket(bucketName, location);

        S3Object fileObject = null;
        try {
            fileObject = new S3Object(file);
            fileObject.setKey(key);//如果设置了key 在创建访问链接的时候要使用这个key作为文件名
            fileObject = s3Service.putObject(euBucket, fileObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileObject;
    }

1.2.8 获取s3存储桶中文件的访问链接

/**
     * 创建s3访问链接
     *
     * @param euBucket
     * @param fileName
     * @return
     */
    @Override
    public String createSignedUrl(String euBucket, String fileName) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, 50);
        Date expiryDate = cal.getTime();
        String signedUrl = s3Service.createSignedGetUrl(euBucket, fileName, expiryDate, false);

        BouncyCastleProvider provider = new BouncyCastleProvider();

        return signedUrl;
    }

以上就基本实现了文件的上传及访问链接的生产,链接可以设置多长时间失效。


二,使用amazon CloudFront为s3存储文件创建cdn分发

2.1,进入CloudFront控制台

2.1.1创建分配 如下图6

图6

2.1.2 选择s3存储桶作为源域名 如下图7

图7

2.1.3 创建完成之后需要授予cloudfront对s3的访问权限,如下设置源和源组

图8

2.1.4 授予对存储桶的读取权限

图9

2.1.5 此时就可以使用cloudfront分配给你的域名来访问你的s3资源了 域名如下图10

图10

然后你就可以直接用这个域名访问s3存储桶中的文件


2.2 为cloudfront设置ssl访问 (我是使用自己的域名来做ssl访问的 域名为tokyo.imdou8.com)

2.2.1 编辑分配 设置备用域名(CNAMEs)如下图11

图11

2.2.2 进入自己的域名供应商设置界面 设置域名(tokyo.imdou8.com)的cname指向cloudfront分配给你的域名如(dxxxxxxxd42gq.cloudfront.net) 如下图12

图12

然后你就可以通过自己的域名来访问cloudfont分发的s3资源了


2.3 以上步骤完成后,你可以通过自己的域名来访问cloudfront在全球边缘节点分发的s3资源,速度会比直接访问s3要快。但是此时你会发现访问是不可信的ssl连接。以下是为cloudfront配置ssl证书

2.3.1 进入amazon 证书管理控制台 如下图13

图13

填写域名

图14

2.3.2 由于不知道dns怎么验证,所以我选择的是邮件验证,如果是你自己的域名,选择邮件验证后amazon会给你发送一封邮件
 

图15

邮件截图如下 直接点击邮件中的链接进行验证

图16

点击i approve 然后可以看到验证成功

图17

2.3.3 回到cloudfront控制台 进入编辑分配页面 选择刚才分配的证书 并保存设置 如下图18

图18

由此,及完成了ssl证书的设置 再访问cloudfront链接就是已授信链接了


2.4 通过编程生成授信cloudfront链接

2.4.1 在amazon网站右上角用户名下拉列表中找到"我的安全凭证" 点击进入

图19

2.4.2 创建cloudfront秘钥对 获取一个pk-APKAJXXXXXXXPREKE3PFA.pem

图20

2.4.3 通过pem文件生成.der文件 获取cdnPK.der
 

openssl pkcs8 -topk8 -nocrypt -in pk-APKAJCHZMNRPREKE3PFA.pem -inform PEM -out cdnPK.der -outform DER

2.4.5 编程获取ssl链接

/**
     * 获取cloudfont访问链接
     *
     * @param domain
     * @param privateKeyPath
     * @param keyPairId
     * @param s3ObjectKey
     * @return
     */
    @Override
    public String privateS3Url(String domain, String privateKeyPath, String keyPairId, String s3ObjectKey) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, 50);
        String signedUrl = null;
        try {
            String policyResourcePath = "https://" + domain + "/" + s3ObjectKey;
            byte[] derPrivateKey = ServiceUtils.readInputStreamToBytes(new
                    FileInputStream(privateKeyPath));
//
//            String signedUrlCanned = CloudFrontService.signUrlCanned(
//                    policyResourcePath,
//                    keyPairId,
//                    derPrivateKey,
//                    ServiceUtils.parseIso8601Date(sdf.format(cal.getTime())) // DateLessThan
//            );
//

            String policy = CloudFrontService.buildPolicyForSignedUrl(
                    policyResourcePath,
                    ServiceUtils.parseIso8601Date(sdf.format(cal.getTime())),
                    "0.0.0.0/0",
                    ServiceUtils.parseIso8601Date(sdf.format(new Date().getTime()))
            );

            signedUrl = CloudFrontService.signUrl(
                    policyResourcePath,
                    keyPairId,
                    derPrivateKey,
                    policy
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return signedUrl;
    }

以上可以获取一个授信的https链接 如下

https://tokyo.imdou8.com/vid/20190104/1f1652c9953744b2bc7435a98b472692.mp4?Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6Imh0dHBzOi8vdG9reW8uaW1kb3U4LmNvbS92aWQvMjAxOTAxMDQvMWYxNjUyYzk5NTM3NDRiMmJjNzQzNWE5OGI0NzI2OTIubXA0IiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNTUwOTEzMzk5fSwiSXBBZGRyZXNzIjp7IkFXUzpTb3VyY2VJcCI6IjAuMC4wLjAvMCJ9LCJEYXRlR3JlYXRlclRoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTU0NjU5MzM5OX19fV19&Signature=3CEaJ3JFf4YwIwvl17nJO-9Eopp3QW~~6wwx7sOyJ~d4jwyTg1dko5UEy6rRPQ89s9mtzrv114UhkLcgvrX~BV1AwsucBkGusvPOMdyf1P5SibMorVJdMvN0GuZx8wWqUWEebxgDnJP0JhBmwNj8v9zsN5uz9BYZaTavkwkeVT9XPfE~hbDIhNOjBz9ciqWyM8x4wQUDWWJUWV-~BAiYuKA-yyPajnluXsDzia7pVonI8TLSuUGFnPLBzCeqhEkt7LWLhlzQzOCUMB0-~DKTMbj0giVkM3O728lBewJvDyhs77nOPdQOjFoleyFNVvP1iq~879~7H1~y6xRrspz4pA__&Key-Pair-Id=APKAJCHZMNRPREKE3PFA

ok this all

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值