F-Lab
🚀
상위권 IT회사 합격 이력서 무료로 모아보기

스프링 시큐리티와 JWT를 이용한 인증 시스템 구현

writer_thumbnail

F-Lab : 상위 1% 개발자들의 멘토링

AI가 제공하는 얕고 넓은 지식을 위한 짤막한 글입니다!



스프링 시큐리티와 JWT를 이용한 인증 시스템 구현

현대 웹 애플리케이션에서는 사용자 인증이 필수적입니다. 스프링 시큐리티와 JWT(Json Web Token)를 이용하면 안전하고 확장 가능한 인증 시스템을 구현할 수 있습니다.

스프링 시큐리티는 강력한 보안 기능을 제공하며, JWT는 토큰 기반 인증을 통해 서버의 상태를 유지하지 않고도 인증을 처리할 수 있습니다. 이 글에서는 스프링 시큐리티와 JWT를 이용한 인증 시스템 구현 방법을 알아보겠습니다.

왜냐하면 JWT는 서버의 상태를 유지하지 않고도 인증을 처리할 수 있기 때문입니다. 이는 서버 부하를 줄이고 확장성을 높이는 데 도움이 됩니다.

스프링 시큐리티와 JWT를 이용한 인증 시스템 구현은 복잡하지만, 이를 통해 안전하고 확장 가능한 인증 시스템을 구축할 수 있습니다.

이 글에서는 스프링 시큐리티와 JWT를 이용한 인증 시스템 구현 방법을 단계별로 설명하고, 실제 코드 예제를 통해 이해를 돕겠습니다.



스프링 시큐리티 설정

스프링 시큐리티를 설정하기 위해서는 먼저 의존성을 추가해야 합니다. Maven을 사용하는 경우, pom.xml 파일에 다음과 같이 의존성을 추가합니다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

왜냐하면 스프링 시큐리티와 JWT를 사용하기 위해 필요한 라이브러리를 추가해야 하기 때문입니다. 이를 통해 보안 기능을 구현할 수 있습니다.

의존성을 추가한 후, 스프링 시큐리티 설정 클래스를 작성합니다. 이 클래스에서는 인증 및 인가 설정을 정의합니다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

이 설정을 통해 인증이 필요한 경로와 그렇지 않은 경로를 정의할 수 있습니다. 또한, 세션을 사용하지 않도록 설정합니다.



JWT 토큰 생성 및 검증

JWT 토큰을 생성하고 검증하기 위해서는 JWT 라이브러리를 사용합니다. 먼저, 토큰을 생성하는 메소드를 작성합니다.

public String generateToken(UserDetails userDetails) {
    Map claims = new HashMap<>();
    return Jwts.builder()
            .setClaims(claims)
            .setSubject(userDetails.getUsername())
            .setIssuedAt(new Date(System.currentTimeMillis()))
            .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
            .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
            .compact();
}

왜냐하면 JWT 토큰은 사용자 정보를 포함하고, 서명된 토큰을 반환하기 때문입니다. 이를 통해 인증된 사용자를 식별할 수 있습니다.

다음으로, 토큰을 검증하는 메소드를 작성합니다.

public Boolean validateToken(String token, UserDetails userDetails) {
    final String username = getUsernameFromToken(token);
    return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}

이 메소드는 토큰의 유효성을 검사하고, 토큰이 만료되지 않았는지 확인합니다. 이를 통해 안전한 인증을 보장할 수 있습니다.



스프링 시큐리티 필터 설정

스프링 시큐리티 필터를 설정하여 JWT 토큰을 검증하고, 인증된 사용자 정보를 설정합니다. 먼저, JWT 필터 클래스를 작성합니다.

public class JwtRequestFilter extends OncePerRequestFilter {
    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        final String requestTokenHeader = request.getHeader("Authorization");
        String username = null;
        String jwtToken = null;
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            } catch (IllegalArgumentException e) {
                System.out.println("Unable to get JWT Token");
            } catch (ExpiredJwtException e) {
                System.out.println("JWT Token has expired");
            }
        } else {
            logger.warn("JWT Token does not begin with Bearer String");
        }
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }
}

왜냐하면 이 필터는 요청 헤더에서 JWT 토큰을 추출하고, 토큰을 검증하여 인증된 사용자 정보를 설정하기 때문입니다. 이를 통해 요청이 안전하게 처리될 수 있습니다.

다음으로, 이 필터를 스프링 시큐리티 설정에 추가합니다.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/api/auth/**").permitAll()
        .anyRequest().authenticated()
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}

이 설정을 통해 JWT 필터가 스프링 시큐리티 필터 체인에 추가됩니다. 이를 통해 모든 요청이 JWT 토큰을 통해 인증됩니다.



결론

스프링 시큐리티와 JWT를 이용한 인증 시스템 구현은 복잡하지만, 이를 통해 안전하고 확장 가능한 인증 시스템을 구축할 수 있습니다.

왜냐하면 JWT는 서버의 상태를 유지하지 않고도 인증을 처리할 수 있기 때문입니다. 이는 서버 부하를 줄이고 확장성을 높이는 데 도움이 됩니다.

스프링 시큐리티와 JWT를 이용한 인증 시스템 구현은 복잡하지만, 이를 통해 안전하고 확장 가능한 인증 시스템을 구축할 수 있습니다.

이 글에서는 스프링 시큐리티와 JWT를 이용한 인증 시스템 구현 방법을 단계별로 설명하고, 실제 코드 예제를 통해 이해를 돕겠습니다.

이를 통해 안전하고 확장 가능한 인증 시스템을 구축할 수 있습니다.

ⓒ F-Lab & Company

이 컨텐츠는 F-Lab의 고유 자산으로 상업적인 목적의 복사 및 배포를 금합니다.

조회수
logo
copyright © F-Lab & Company 2025