반응형
JWT (JSON Web Token)과 OAuth 2.0을 조합하여 다중 인증 방식을 구현하는 방법을 다룹니다.
이 통합 방식은 다양한 인증 요구 사항을 처리하며, 확장성과 보안성을 동시에 제공합니다.
1. 다중 인증 방식의 필요성
1-1. JWT와 OAuth 2.0의 특징
- JWT
- 클라이언트와 서버 간에 인증 정보를 주고받기 위해 사용.
- 간단하고 독립적인 인증 토큰으로 사용.
- 보안 민감도가 낮은 서비스에 적합.
- OAuth 2.0
- 인증 및 권한 부여를 포함한 복잡한 보안 요구 사항을 지원.
- 외부 API 및 서드파티 앱과 통합이 용이.
- 보안 민감도가 높은 서비스에 적합.
1-2. 다중 인증 방식 통합의 필요성
- OAuth 2.0을 통해 초기 사용자 인증을 처리한 후, JWT를 사용해 지속적인 요청을 처리합니다.
- JWT는 빠르고 간단한 인증 처리에 적합하며, OAuth 2.0은 고급 보안을 제공합니다.
2. 구현 계획
- OAuth 2.0을 통해 Access Token 발급.
- Access Token으로 JWT 생성.
- JWT를 사용하여 API 요청 처리.
- 특정 요청에 대해 OAuth 2.0 토큰 재검증 지원.
3. 구현 코드
3-1. OAuth 2.0에서 JWT 생성
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Service
public class JwtTokenService {
private static final String SECRET_KEY = "jwtSecretKey";
public String generateJwtFromOauthToken(String oauthAccessToken, String username) {
Map<String, Object> claims = new HashMap<>();
claims.put("oauthAccessToken", oauthAccessToken);
return Jwts.builder()
.setClaims(claims)
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1시간 유효
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
}
3-2. JWT 기반 요청 처리
커스텀 필터를 사용해 JWT를 검증하고 사용자 정보를 로드합니다.
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final String SECRET_KEY = "jwtSecretKey";
private final UserDetailsService userDetailsService;
public JwtAuthenticationFilter(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authorizationHeader = request.getHeader("Authorization");
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
String token = authorizationHeader.substring(7);
try {
Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
String username = claims.getSubject();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
JwtAuthenticationToken authentication = new JwtAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
SecurityContextHolder.clearContext();
}
}
chain.doFilter(request, response);
}
}
3-3. 다중 인증 설정
Spring Security 설정 파일에서 두 가지 인증 방식을 통합합니다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final CustomAuthenticationFilter oauthAuthenticationFilter;
public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter, CustomAuthenticationFilter oauthAuthenticationFilter) {
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
this.oauthAuthenticationFilter = oauthAuthenticationFilter;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(oauthAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtAuthenticationFilter, CustomAuthenticationFilter.class);
return http.build();
}
}
4. 테스트
- OAuth 2.0 토큰 발급:
- 권한 서버에서 Access Token을 발급받습니다.
- JWT 생성:
- OAuth 2.0 Access Token으로 JWT를 생성합니다.
- API 호출:
- JWT를 사용하여 인증된 API 요청을 테스트합니다.
- 잘못된 JWT는 403 Forbidden을 반환해야 합니다.
- 다중 인증 확인:
- 요청이 OAuth 2.0 또는 JWT 중 하나로 성공적으로 인증되는지 확인합니다.
5. 마무리
이번 학습에서는 JWT와 OAuth 2.0을 통합한 다중 인증 시스템을 설계하고 구현했습니다. 이를 통해 다양한 보안 요구 사항을 처리할 수 있는 확장성 높은 인증 체계를 구축할 수 있었습니다.
다음에서는 전자정부프레임워크의 인증 로그 관리에 대해 다룹니다.
반응형
'개발 > 전자정부프레임워크' 카테고리의 다른 글
전자정부프레임워크에서 역할 기반 권한 관리(Role-Based Access Control) 구현 (0) | 2024.12.26 |
---|---|
전자정부프레임워크에서 인증 로그 관리 구현 (0) | 2024.12.26 |
OAuth 2.0 커스텀 인증 필터 구현 (0) | 2024.12.26 |
Refresh Token 전략과 로그아웃 구현 (1) | 2024.12.26 |
OAuth 2.0 기반 API 요청 및 Access Token 검증 (0) | 2024.12.26 |