1단계: 비밀번호 해시와 JWT 로그인
7. 정리
- 비밀번호는 느린 해시(PBKDF2/bcrypt/Argon2) + 사용자별 salt 로 저장하고, 반복 횟수·알고리즘을 해시 문자열에 함께 기록해 점진적으로 강화한다. 비교는
MessageDigest.isEqual로 상수 시간에 한다. - JWT =
base64url(header).base64url(payload).base64url(signature). 페이로드는 누구나 읽는다. 서명이 변조를 막을 뿐이다. 비밀은 넣지 않고 크기는 작게. - HS256 은 비밀키 공유(단일 서비스), RS256 은 공개키 배포(여러 리소스 서버). 비밀키는 256비트 난수를 외부에서 주입.
- 검증은 ① 기대 alg 고정 → ② 서명 → ③ exp/nbf(leeway) 순서. 헤더의 alg 를 믿으면
none·키 혼동 공격에 뚫린다. - 보호 자원은
Authorization: Bearer로 받고, 401(누군지 모름)과 403(권한 없음)을 구분하며, 헤더에는 ASCII 만 쓰고, 토큰 응답에는no-store를 붙인다. - 로그인 엔드포인트는 존재 여부를 노출하지 않고(같은 메시지 + 더미 해시), 실패 횟수로 잠그되 서비스 거부가 되지 않게 설계한다.
- Spring Security + jjwt 는
PasswordEncoder,Jwts.builder/parser,OncePerRequestFilter,authorizeHttpRequests로 이 레슨의 각 부분을 1:1 로 대신한다.
다음 2단계 에서는 "발급한 토큰을 취소할 수 없다"는 JWT 의 약점을 Access/Refresh 토큰 분리와 회전으로 다루고, 우리 서버가 아닌 외부(구글·회사 SSO)에 인증을 위임하는 OAuth2 인가 코드 흐름을 인가 서버·리소스 서버·클라이언트 세 역할로 나눠 구현합니다.