JWT와 OAuth 2.0을 이용한 sso와 비슷한 통합 인증 처리 방식을 구현하고 나서 정리하기 위해서 작성 되었다.
여러 방식 중에 두가지 방식을 보면
1. A 시스템에서 B 시스템의 api를 사용하고 싶을때 (Header 기반 인증 방식)
authentication의 header에 담아서 이용 .
헤더를 통해 JWT를 전달하는 것은 API 호출과 같은 서버 간 통신에서 주로 사용됨. (주로 사용하는 방식)
ex)
# A 시스템 (http://localhost:8081)
@PostMapping("/authenticate")
public ResponseEntity<String> authenticate(@RequestParam String username) {
// JWT 생성
String jwtToken = jwtService.generateToken(username);
return ResponseEntity.ok(jwtToken);
}
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(jwtToken); // Authorization 헤더에 JWT 추가
HttpEntity<?> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
"http://localhost:8082/api/protected",
HttpMethod.GET,
requestEntity,
String.class
);
System.out.println("Response: " + response.getBody());
=> B 시스템꺼 호출
# B 시스템 (http://localhost:8082)
@RestController
@RequestMapping("/api")
public class ProtectedApiController {
@GetMapping("/protected")
public ResponseEntity<Map<String, Object>> getProtectedData(Authentication authentication) {
if (authentication == null || !authentication.isAuthenticated()) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("error", "Unauthorized"));
}
String username = authentication.getName(); // JWT의 sub 클레임
return ResponseEntity.ok(Map.of(
"message", "Access granted to protected resource",
"username", username
));
}
}
위처럼 header에서 담아서 토큰을 보내고 해당 토큰을 oauth2ResourceServer을 통해 검증 받고 나서 B의 api의 내용을 a system에다가 호출 하게끔 해준다.
# process
1. Spring Security의 oauth2ResourceServer 설정이 헤더에서 JWT를 자동으로 추출.
2. JwtDecoder를 사용하여 JWT를 검증:
3. 서명 검증: 토큰이 위조되지 않았는지 확인.
4. 만료 검증: exp 클레임 확인.
5. 검증이 성공하면, JWT의 클레임 정보를 바탕으로 Authentication 객체를 생성.
6. A 시스템에서 해당 api 사용
# 헤더 기반 인증의 장점
보안 강화: JWT는 요청마다 Authorization 헤더에 추가되므로, 쿠키의 CSRF 공격을 방지할 수 있다.
명확한 인증 흐름: JWT는 인증 정보를 클라이언트가 명시적으로 전달하기 때문에, 여러 시스템 간의 인증이 명확히
구분 된다.
유연성: 클라이언트가 원하는 방식으로 헤더를 설정해 다양한 API 호출에 활용할 수 있다.
# 헤더 기반 인증의 실무 활용
API 호출: A 시스템에서 발급받은 JWT를 사용해 B 시스템의 API를 호출할 때 주로 사용됨.
서버 간 통신: 마이크로서비스 구조에서, A 시스템의 서버가 B 시스템의 서버로 API를 호출할 때 헤더에 JWT를 포함.
브라우저 사용 제한: 브라우저가 아닌 API 클라이언트(예: Postman, Java 클라이언트 등)가 주로 사용.
2. cookie에 jwt를 담아서 사용하는 방식. (LIKE SSO)
# process
1. OAuth 2.0을 통한 JWT 발급:
A 시스템에서 사용자를 인증하고 JWT를 발급합니다.
JWT는 issuer, subject, claims 등을 포함하여 A 시스템에서 서명된 토큰 (JwtEncoder 도 사용)
2. JWT를 사용한 인증 연계:
B 시스템은 A 시스템에서 발급된 JWT를 받아 이를 검증(JwtDecoder 및 JWK 설정)
JWT를 디코드하여 사용자 정보(username, roles, businessId 등)를 추출하고, 이를 통해 Spring Security 컨텍스트에 인증 정보를 설정합니다.
3. 쿠키 기반 JWT 전달:
A 시스템에서 발급된 JWT를 클라이언트 브라우저의 쿠키에 저장(JWT_TOKEN).
리디렉션 후에도 B 시스템에서 클라이언트가 전달한 JWT 쿠키를 통해 인증
4. B 시스템에서 인증 보호:
/menu와 같은 경로는 인증된 사용자만 접근 가능하도록 설정.
JWT를 사용하여 B 시스템에서 독립적으로 사용자 인증 및 권한 확인.
=> 이렇게 사용하는 이유가 A 시스템에서 B 시스템으로 이동되는 redirect 메뉴가 있을시에, redirect에는 header을 담지 못하기 때문에 사용한다.
# cookie에 jwt의 장점
SSO 구현: 한 번의 로그인(A 시스템)으로 B 시스템에서도 인증된 사용자로 접근 가능.
분산 인증: A 시스템과 B 시스템은 서로 독립적이면서도 JWT를 통해 연계.
확장 가능성: 추가 시스템(C, D 등)을 연결하기 쉬움. 각 시스템은 JWT 검증만 추가하면 됨.
보안성: JWT 서명을 통해 토큰 위조를 방지. HTTPS 환경에서 쿠키로 안전하게 전달.
# 실무
이 구조도 실무에서 많이 사용한다고 한다.
A 시스템 JWT 발급 => B 시스템 이를 검증하고 사용자 인증.
마이크로서비스 또는 시스템 간 인증 연계에 적합한 방식.
경험상 공기업에서 많이 썼다.
'개발 > Spring Boot' 카테고리의 다른 글
[JPA] LifeCycle Callback을 조종할 수 있게하는 어노테이션 (0) | 2025.01.24 |
---|---|
[maven] intellij springboot jsp 인식 안될 때 사용 (0) | 2023.03.30 |
[SpringBoot] @RequiredArgsConstructor 필요없는 소스 리팩토링 필드 주입 & 생성자 주입 차이 TIL (0) | 2023.03.03 |
[Spring]log4j, @Slf4j 사용법 (0) | 2023.01.19 |
[springBoot] 내장 톰캣 Server port 변경 (0) | 2022.12.01 |