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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章