-
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(snackgame.biz): 게임 결과를 서명한다 #179
Conversation
b4f436c
to
a242fbf
Compare
a242fbf
to
6e0049b
Compare
7cf5156
to
6e0049b
Compare
class ResponseSigner( | ||
val signer: Signer, | ||
val objectMapper: ObjectMapper | ||
) : ResponseBodyAdvice<Any> { |
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.
ResponseBodyAdvice
가 공통된 응답을 위해 쓰인다고 하는데 지금처럼 DTO를 만들어서 하던 방법과 차이점이나 ResponseBodyAdvice
를 쓰게 된 이유가 있을까요??
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.
선요약: 최소한의 접점만으로 문제를 가장 직접적으로 해결하는 방법이다
이것도 풀자면 긴 스토리긴 한데요.
우선 목적은 최대한 기존 코드를 건드리지 않고 반환값을 서명하는 것입니다. (서명에 대한 관심사 분리)
물론 멋있다는 점도 한 몫 합니다 ㅋ.ㅋ
원래 HandlerMethodReturnValueHandler 혹은 HandlerInterceptor를 사용하려고 했습니다. (둘 다 실패)
전자는 @ResponseBody
에 대한 ReturnValueHandler가 이미 있기 때문에 제가 새로 추가한 핸들러가 실행되지 않아서 실패했구용
후자는 HttpServletResponse의 body를 조작해야 하는데, 이 body는 이미 String이 된 상태이므로 조작이 조금 복잡해지며 부작용의 우려가 있습니다.
이것보다 더 직접적인 방법(ResponseBodyAdvice)가 있어 이걸 선택했습니다.
ResponseBodyAdvice 인터페이스는 이름처럼 @ResponseBody
를 처리하는데 참고자료의 역할을 할 수 있습니다. (Spring API 문서)
말씀해주신 목적으로도 사용하긴 하는 것 같은데,
특별히 '공통된 응답을 만드는데 사용하라' 같은 의도는 없는 것으로 보입니다.
그래서 앞서 말씀드린 목적으로 사용할 수 있다고 생각했구요,
이 친구의 작동방식을 고려해보면 - 실제로 MessageConverter가 바디를 변환하기 직전!에 작동하므로, 변환하고자 하는 값을 직접적으로(타입도 살아있는 상태로) 받고 제어할 수 있게 됩니다.
이 틈에 기존 객체에 서명하고 감쌈으로써 최소한의 접점만으로 원하는 목적을 달성하는 AOP를 할 수 있게 됩니다.
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.
역시 땡칠... 어노테이션만으로 처리할 수 있게 된게 인상적입니다..
오늘도 하나배워갑니다
|
||
return Jwts.builder() | ||
.header().keyId(privateKey.hashCode().toString()) |
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.
keyId
를 추가하는 것은 무엇을 위한 작업인가요??
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.
이 부분은 스낵게임 Biz 문서 하단을 보시면 이해가 쉬울 것 같은데요.
RSASHA로 서명된 JWT는 공개키인 JWK로 검증이 가능합니다.
이 JWK를 여러개 묶어놓은게 JWKS(JSON Web Key Set)인데요.
그 키들 중에서 해당 JWT에 맞는 공개키를 찾는데 kid를 사용할 수 있습니다.
이렇게 되면 '키 순환'이 가능해진다는 장점도 있습니다.
만일 기존 키페어의 유출/분실 사고가 발생한다면 키셋에서 해당 키를 제거하고 새 키페어를 등록해줄 수 있습니다.
그러면 기존 JWT는 검증에 실패하고, 새 키페어로 서명된 JWT는 검증이 잘 되겠죠?
이런 장점들 때문에 서명에 사용한 keyId를 적고, 키를 관리하는 것이 좋습니다.
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.
아하 이해했습니다! 자세한 설명 감사드립니다 🫢
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.
이번 작업도 너무 고생하셨습니다! 심사도 완료돼서 이제 다음단계로 나아갈 수 있을 것 같네요 ㅎㅎ
관련 이슈
변경 사항
AS-IS
스낵게임 Biz의 게임 결과가 평문이기 때문에 타 비즈니스에서 신뢰할 수 없었습니다
TO-BE
RS256 알고리즘을 통해 게임 결과를 서명합니다.
서명된 게임 결과는 스낵게임 Biz에서 제공하는 공개키를 사용해 검증할 수 있습니다.
자세한 문서는 블로그에 기록했습니다: https://biz.snackga.me
Rest 컨트롤러 메서드에
![image](https://private-user-images.githubusercontent.com/39221443/374906961-299e855b-f2ef-4eb0-8dfb-6226333feaf0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzg5NTYzODMsIm5iZiI6MTczODk1NjA4MywicGF0aCI6Ii8zOTIyMTQ0My8zNzQ5MDY5NjEtMjk5ZTg1NWItZjJlZi00ZWIwLThkZmItNjIyNjMzM2ZlYWYwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMDclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjA3VDE5MjEyM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTFmMGNmNmI0YmJlNzE2YzYzNTQzOWQ5NDg3ZWVjYzlkNjE0MzgxZGRlNzhhYTNkNmZkNDg1OWI0NzcwNDQxZTUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.HUgSGmm5VW3OzV-JF-T4wRb21azoy21NrnM2FtNSK30)
@Signed
어노테이션을 붙여 서명할 수 있습니다