개인 정보기 때문에 경로는 가려놓았다.
버킷은 (가명) private-image-test
디렉토리는 private_images로 생성했다.
사진이 올라가는 경로는 private-image-test/private_images 이다.
주의)반드시 모든 퍼블릭 엑세스 차단 할것!!!
(s3 origin으로 다이렉트로 접근하여 파일을 읽지 못하게 할것)
퍼블릭–프라이빗 키 페어를 생성
OpenSSL을 사용하여 길이가 2048비트인 RSA 키 페어를 생성하고 private_key.pem이라는 파일에 저장
openssl genrsa -out private_key.pem 2048
이렇게 만들어진 파일은 퍼블릭 키와 프라이빗 키를 모두 포함합니다. 다음 예제 명령은 private_key.pem이라는 파일에서 퍼블릭 키를 추출
openssl rsa -pubout -in private_key.pem -out public_key.pem
CloudFront에 퍼블릭 키 생성 및 업로드
cat public_key.pem
b. cloudfront key group 생성 및 해당 group에 위에서 생성한 public keys id 등록 (그룹으로 key들을 관리)
c. cloudfront 생성 및 버킷 연결
(참고) cloudfront 주요 설정들
cloudfront url 대신 사용할 도메인 이름 등록
s3 origin domain 등록 및 oai 생성 및 등록 (s3 bucket 에 해당 cloudfront oai 로만 접근 가능하도록 함)
→ 주의) 이때, bucket policy 부분 선택 란에 "yes, update th bucket policy"를 선택해야, 연결된 s3 버킷의 정책을 자동으로 업데이트함
"yes, update th bucket policy" 선택하고 저장 시 s3 정책에 아래와 같은 내용이 추가됨
위에서 생성한 키 페어의 프라이빗 키를 활용해 cloudfront signed url 를 만들어 접근하도록 구현
또한 해당 url에 만료 날짜 및 시간을 설정하여 접근을 제어 (최초 signed url 생성 후 1분간만 유효)
(참고) cloudfront signed url 생성을 java에서 구현하기 위해서는 pem 형식의 프라이빗 키를 der 형식으로 변환해야 함
openssl pkcs8 -topk8 -nocrypt -in private_key.pem -inform PEM -out private_key.der -outform DER
위에서 생성한 프라이빗 키로 signed url을 만드는 코드
public <T> String createSignedUrlCanned(Tinstance,String columnName,String fileName) {
String policyResourcePath = "https://cdn-daria.daria.com/private_images/" +![](https://velog.velcdn.com/images%2Fjynam821%2Fpost%2F3fd70fdb-034f-4c38-aac2-992ea3d42bed%2Fimage.png) fileName;
// url 유효 기간은 1분
Date expirationDate = new Date(System.currentTimeMillis() +60*1000);
try {
String signedUrlCanned = CloudFrontService.signUrlCanned(
policyResourcePath,// Resource URL or Path
keyPairId,// cloudfront public key id
derPrivateKey,// DER Private key data
expirationDate
);
return signedUrlCanned;
} catch (CloudFrontServiceException e) {
e.printStackTrace();
log.error("createSignedUrlCanned error : " + e.getMessage());
}
return "";
}
ex) 생성된 signed url 예
"https://cdn-daria.daria.com/private_images/z63161_210721030154.jpg?Expires=1626837809&Signature=y64koLxR7~0lzypeiByGmtXr4i8JRz-s8G-h01UXiml8sXnlp-Z4ZhVH2dJO~7TcjqPQCsZcHAs-Q2NbsDtBWje5TNu6PKeLKajLd0cHP-LvYFRBG8PiyRbdQ4ZKxCtAUgzGPszAg-h0E0BuNdXKXmjDOC6R2txBICISyfOAA-i5dIyILPCWNO1gaQC9BFsmymKdHFuQ41FEB15cnucWYy9xBuIJWayKIT4Mh4FJrrHlfQeOB1U~K4GHDDfpq16YkIytZiTxlU5Oe6NhL~bUjY8KXzCGPTWsceqkQMXmIBv73NcZA4pm-Af-9phpIdoywn2TSYBJ16NODNdHaH8yNQ__&Key-Pair-Id=K3LB05P48C0WX"
no-cache는 캐시를 저장하되 캐시가 유효한지 매번 서버에 질의하는 것이고, no-store는 아예 캐시를 저장하지 않는 것이다.
완벽한 캐싱 방지를 위해서는 헤더 설정을 이렇게 할 수 있다.
(참고 : https://aws.amazon.com/ko/premiumsupport/knowledge-center/prevent-cloudfront-from-caching-files/)
Cache-Control: no-cache, no-store, must-revalidate
이미지를 s3에 upload 시 아래와 같이 메타데이터에 위의 cache-control 내용을 추가한다.
// 메타데이터에 해당 정보를 실어보내지 않으면 s3에서 이미지 url 접근시 새창으로 보여지는 게 아니라 무조건 다운로드가 됨.
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
metadata.setCacheControl("no-cache, no-store, must-revalidate");
metadata.setContentLength(file.getSize());