对于前期用户量不大但是需要稳定服务的项目,S3和Cloudfront是个不错的选择
一,申请amazon 账户 申请过程不再介绍 我是在淘宝上买一张1美元的万事达卡来申请的,成本10块钱左右
1.1,等待申请通过后进入控制台 在所有服务中找到存储 ->s3 (如下图1)如果amazon账号申请已经通过 进入页面就可以直接在页面创建存储桶,我是需要通过编程的方式上传文件,所以这里不再介绍在页面创建存储桶的过程,可以自己玩玩摸索一下
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
1.2.2,获取访问授权的另一种方式(与1.2.1作用相同,都是为了获取对s3访问的凭证,1.2.1和1.2.2可以自己选择用哪种方式)
进入IAM控制台 如下图3 这里相当于建立了amazon的子账户,可以设置这些子账户的访问权限,比如你可以建一个账户只能对s3进行操作,你拿到这个子账户的授权key就只能在代码里访问或者操作s3的资源内容
1.2.3 创建用户 如图4
1.2.4 创建成功后会给你一个秘钥,这个秘钥就是访问s3的凭证
1.2.5 当然,要为用户添加访问s3的权限,如图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
2.1.2 选择s3存储桶作为源域名 如下图7
2.1.3 创建完成之后需要授予cloudfront对s3的访问权限,如下设置源和源组
2.1.4 授予对存储桶的读取权限
2.1.5 此时就可以使用cloudfront分配给你的域名来访问你的s3资源了 域名如下图10
然后你就可以直接用这个域名访问s3存储桶中的文件
2.2 为cloudfront设置ssl访问 (我是使用自己的域名来做ssl访问的 域名为tokyo.imdou8.com)
2.2.1 编辑分配 设置备用域名(CNAMEs)如下图11
2.2.2 进入自己的域名供应商设置界面 设置域名(tokyo.imdou8.com)的cname指向cloudfront分配给你的域名如(dxxxxxxxd42gq.cloudfront.net) 如下图12
然后你就可以通过自己的域名来访问cloudfont分发的s3资源了
2.3 以上步骤完成后,你可以通过自己的域名来访问cloudfront在全球边缘节点分发的s3资源,速度会比直接访问s3要快。但是此时你会发现访问是不可信的ssl连接。以下是为cloudfront配置ssl证书
2.3.1 进入amazon 证书管理控制台 如下图13
填写域名
2.3.2 由于不知道dns怎么验证,所以我选择的是邮件验证,如果是你自己的域名,选择邮件验证后amazon会给你发送一封邮件
邮件截图如下 直接点击邮件中的链接进行验证
点击i approve 然后可以看到验证成功
2.3.3 回到cloudfront控制台 进入编辑分配页面 选择刚才分配的证书 并保存设置 如下图18
由此,及完成了ssl证书的设置 再访问cloudfront链接就是已授信链接了
2.4 通过编程生成授信cloudfront链接
2.4.1 在amazon网站右上角用户名下拉列表中找到"我的安全凭证" 点击进入
2.4.2 创建cloudfront秘钥对 获取一个pk-APKAJXXXXXXXPREKE3PFA.pem
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