-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEAT] S3 PreSignedUrl 발급 로직 구현 #48
Merged
Merged
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
14d96a5
[REFACTOR] S3Service에서 CloudFront 로직 분리하여 CloudService 추가
sung-silver 7b29d52
[FIX] naver 소셜 로그인 YML 변경에 따른 Value 경로 수정
sung-silver 95c1433
[DEL] 안쓰는 import문 삭제
sung-silver 6df55ba
[FEAT] S3 Service내에서 getUploadPreSignedUrl 구현
sung-silver 5ac21a4
[ADD] S3 Bucket 폴더 이름 static 변수로 분리해서 추가
sung-silver 0b4896f
[CHORE] CI/CD SCRIPT내 cloudfront-private-key 생성 코드 추가
sung-silver File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
import com.nonsoolmate.nonsoolmateServer.domain.university.exception.UniversityExamException; | ||
import com.nonsoolmate.nonsoolmateServer.domain.university.exception.UniversityExamExceptionType; | ||
import com.nonsoolmate.nonsoolmateServer.domain.university.repository.UniversityExamImageRepository; | ||
import com.nonsoolmate.nonsoolmateServer.external.aws.service.S3Service; | ||
import com.nonsoolmate.nonsoolmateServer.external.aws.service.CloudFrontService; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
|
@@ -28,7 +28,7 @@ public class UniversityExamService { | |
|
||
private final UniversityExamRepository universityExamRepository; | ||
private final UniversityExamImageRepository universityExamImageRepository; | ||
private final S3Service s3Service; | ||
private final CloudFrontService cloudFrontService; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 따로 분리하는게 맞는거 같네요 좋습니다~! |
||
|
||
|
||
public UniversityExamInfoResponseDTO getUniversityExam(Long universityExamId) { | ||
|
@@ -55,15 +55,15 @@ public UniversityExamImageAndAnswerResponseDTO getUniversityExamImageAndAnswer(L | |
.orElseThrow(() -> new UniversityExamException( | ||
UniversityExamExceptionType.NOT_FOUND_UNIVERSITY_EXAM)); | ||
|
||
String examAnswerUrl = s3Service.createPresignedGetUrl(EXAM_ANSWER_PATH, | ||
String examAnswerUrl = cloudFrontService.createPreSignedGetUrl(EXAM_ANSWER_PATH, | ||
universityExam.getExamAnswerFileName()); | ||
List<UniversityExamImageResponseDTO> examImageUrls = new ArrayList<>(); | ||
|
||
List<UniversityExamImage> UniversityExamImages = universityExamImageRepository.findAllByUniversityExam( | ||
universityExam); | ||
|
||
UniversityExamImages.stream().forEach(universityExamImage -> { | ||
String presignedGetUrl = s3Service.createPresignedGetUrl(EXAM_IMAGE_PATH, | ||
String presignedGetUrl = cloudFrontService.createPreSignedGetUrl(EXAM_IMAGE_PATH, | ||
universityExamImage.getUniversityExamImageFileName()); | ||
|
||
examImageUrls.add( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
...olmateServer/src/main/java/com/nonsoolmate/nonsoolmateServer/external/aws/FolderName.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.nonsoolmate.nonsoolmateServer.external.aws; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class FolderName { | ||
public static final String EXAM_ANSWER_FOLDER_NAME = "exam-answer/"; | ||
public static final String EXAM_RESULT_FOLDER_NAME = "exam-result/"; | ||
public static final String EXAM_SHEET_FOLDER_NAME = "exam-sheet/"; | ||
} | ||
Comment on lines
+6
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 따로 분리하는 거 넘 좋습니다! |
56 changes: 56 additions & 0 deletions
56
...c/main/java/com/nonsoolmate/nonsoolmateServer/external/aws/service/CloudFrontService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package com.nonsoolmate.nonsoolmateServer.external.aws.service; | ||
|
||
import com.amazonaws.services.cloudfront.CloudFrontUrlSigner; | ||
import com.amazonaws.services.cloudfront.util.SignerUtils; | ||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.security.spec.InvalidKeySpecException; | ||
import java.time.Duration; | ||
import java.util.Date; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.ResourceUtils; | ||
|
||
|
||
@Component | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class CloudFrontService { | ||
@Value("${aws-property.distribution-domain}") | ||
private String distributionDomain; | ||
|
||
@Value("${aws-property.private-key-file-path}") | ||
private String privateKeyFilePath; | ||
|
||
@Value("${aws-property.key-pair-id}") | ||
private String keyPairId; | ||
|
||
public String createPreSignedGetUrl(String path, String fileName) { | ||
String s3ObjectKey = path + fileName; // S3 객체 키 | ||
Duration duration = Duration.ofMinutes(1); | ||
Date expirationTime = new Date(System.currentTimeMillis() + duration.toMillis()); | ||
SignerUtils.Protocol protocol = SignerUtils.Protocol.https; | ||
String signedUrl = null; | ||
try { | ||
File privateKeyFile = ResourceUtils.getFile(privateKeyFilePath); | ||
signedUrl = CloudFrontUrlSigner.getSignedURLWithCannedPolicy( | ||
protocol, | ||
distributionDomain, | ||
privateKeyFile, | ||
s3ObjectKey, | ||
keyPairId, | ||
expirationTime | ||
); | ||
} catch (FileNotFoundException e) { | ||
throw new RuntimeException(e); | ||
} catch (InvalidKeySpecException e) { | ||
throw new RuntimeException(e); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
return signedUrl; | ||
} | ||
} |
74 changes: 26 additions & 48 deletions
74
...erver/src/main/java/com/nonsoolmate/nonsoolmateServer/external/aws/service/S3Service.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,50 @@ | ||
package com.nonsoolmate.nonsoolmateServer.external.aws.service; | ||
|
||
import com.amazonaws.services.cloudfront.CloudFrontUrlSigner; | ||
import com.amazonaws.services.cloudfront.util.SignerUtils; | ||
import com.nonsoolmate.nonsoolmateServer.external.aws.config.AWSConfig; | ||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.security.spec.InvalidKeySpecException; | ||
import com.nonsoolmate.nonsoolmateServer.external.aws.service.vo.PreSignedUrlVO; | ||
import java.time.Duration; | ||
import java.util.Date; | ||
import java.util.UUID; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.ResourceUtils; | ||
import org.springframework.stereotype.Service; | ||
import software.amazon.awssdk.services.s3.presigner.S3Presigner; | ||
import software.amazon.awssdk.services.s3.model.PutObjectRequest; | ||
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; | ||
import java.net.URL; | ||
|
||
|
||
@Component | ||
@Service | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class S3Service { | ||
|
||
@Value("${aws-property.s3-bucket-name}") | ||
private String bucketName; | ||
private final AWSConfig awsConfig; | ||
private static final Long PRE_SIGNED_URL_EXPIRE_MINUTE = 1L; | ||
|
||
@Value("${aws-property.distribution-domain}") | ||
private String distributionDomain; | ||
|
||
@Value("${aws-property.private-key-file-path}") | ||
private String privateKeyFilePath; | ||
public PreSignedUrlVO getUploadPreSignedUrl(final String prefix) { | ||
String uuidFileName = generateZipFileName(); | ||
String key = prefix + uuidFileName; | ||
|
||
@Value("${aws-property.key-pair-id}") | ||
private String keyPairId; | ||
S3Presigner preSigner = awsConfig.getS3Presigner(); | ||
|
||
private static final Long PRE_SIGNED_URL_EXPIRE_MINUTE = 1L; | ||
PutObjectRequest putObjectRequest = PutObjectRequest.builder() | ||
.bucket(bucketName) | ||
.key(key) | ||
.build(); | ||
|
||
public String createPresignedGetUrl(String path, String fileName) { | ||
final String key = path + fileName; | ||
String s3ObjectKey = key; // S3 객체 키 | ||
PutObjectPresignRequest preSignedUrlRequest = PutObjectPresignRequest.builder() | ||
.signatureDuration(Duration.ofMinutes(PRE_SIGNED_URL_EXPIRE_MINUTE)) | ||
.putObjectRequest(putObjectRequest) | ||
.build(); | ||
|
||
// 현재 시간에서 1시간 유효한 URL 생성 | ||
Duration duration = Duration.ofHours(1); | ||
Date expirationTime = new Date(System.currentTimeMillis() + duration.toMillis()); | ||
File privateKeyFile = null; | ||
String signedUrl = null; | ||
SignerUtils.Protocol protocol = SignerUtils.Protocol.https; | ||
try { | ||
privateKeyFile = ResourceUtils.getFile(privateKeyFilePath); | ||
URL url = preSigner.presignPutObject(preSignedUrlRequest).url(); | ||
|
||
signedUrl = CloudFrontUrlSigner.getSignedURLWithCannedPolicy( | ||
protocol, | ||
distributionDomain, | ||
privateKeyFile, | ||
s3ObjectKey, | ||
keyPairId, | ||
expirationTime | ||
); | ||
return PreSignedUrlVO.of(uuidFileName, url.toString()); | ||
} | ||
|
||
System.out.println("Signed URL: " + signedUrl); | ||
}catch (FileNotFoundException e){ | ||
log.info("FileNotFoundException = {}", e); | ||
}catch (IOException e){ | ||
log.info("IOException = {}", e); | ||
}catch (InvalidKeySpecException e){ | ||
log.info("InvalidKeySpecException = {}", e); | ||
} | ||
return signedUrl; | ||
private String generateZipFileName() { | ||
return UUID.randomUUID() + ".zip"; | ||
} | ||
|
||
} |
15 changes: 15 additions & 0 deletions
15
...c/main/java/com/nonsoolmate/nonsoolmateServer/external/aws/service/vo/PreSignedUrlVO.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.nonsoolmate.nonsoolmateServer.external.aws.service.vo; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
|
||
@Data | ||
@AllArgsConstructor | ||
public class PreSignedUrlVO { | ||
private String fileName; | ||
private String url; | ||
|
||
public static PreSignedUrlVO of(String fileName, String url) { | ||
return new PreSignedUrlVO(fileName, url); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 이렇게 바꾸니 좋네요! 보안 생각하면 이게 맞겠네요 굿굿!