스프링 부트와 JWT를 활용한 인증 및 권한 부여
F-Lab : 상위 1% 개발자들의 멘토링
AI가 제공하는 얕고 넓은 지식을 위한 짤막한 글입니다!

소개
이번 블로그 포스트에서는 스프링 부트와 JWT(Json Web Token)를 활용하여 인증 및 권한 부여를 구현하는 방법에 대해 다룹니다.
JWT는 JSON 객체를 사용하여 정보를 안전하게 전송하는 데 사용되는 토큰입니다.
스프링 부트는 빠르고 간편하게 웹 애플리케이션을 개발할 수 있는 프레임워크입니다.
이 글에서는 JWT를 사용하여 사용자 인증을 구현하고, 스프링 시큐리티를 활용하여 권한 부여를 설정하는 과정을 단계별로 설명합니다.
왜냐하면 JWT는 안전하고 확장성이 뛰어난 인증 방법을 제공하기 때문입니다.
JWT 설정
JWT를 사용하기 위해서는 먼저 JWT 라이브러리를 설정해야 합니다.
스프링 부트 프로젝트에 JWT 의존성을 추가하고, JWT 토큰을 생성하고 검증하는 유틸리티 클래스를 작성합니다.
예를 들어, build.gradle 파일에 다음과 같이 의존성을 추가할 수 있습니다:
dependencies { implementation 'io.jsonwebtoken:jjwt:0.9.1' }
그리고 JWT 토큰을 생성하고 검증하는 유틸리티 클래스를 작성합니다:
public class JwtUtil { private String secretKey = "secret"; public String generateToken(String username) { return Jwts.builder() .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); } public String extractUsername(String token) { return Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token) .getBody() .getSubject(); } public boolean validateToken(String token, UserDetails userDetails) { final String username = extractUsername(token); return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); } private boolean isTokenExpired(String token) { return Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token) .getBody() .getExpiration() .before(new Date()); } }
왜냐하면 JWT 토큰을 생성하고 검증해야만 안전한 인증을 구현할 수 있기 때문입니다.
사용자 인증 구현
JWT 설정이 완료되면, 이제 사용자 인증을 구현할 수 있습니다.
스프링 시큐리티를 사용하여 사용자 인증을 처리하고, JWT 토큰을 발급합니다.
예를 들어, 사용자 인증을 처리하는 AuthenticationController를 작성합니다:
@RestController public class AuthenticationController { @Autowired private AuthenticationManager authenticationManager; @Autowired private JwtUtil jwtUtil; @PostMapping("/authenticate") public ResponseEntity createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception { try { authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()) ); } catch (BadCredentialsException e) { throw new Exception("Incorrect username or password", e); } final UserDetails userDetails = userDetailsService .loadUserByUsername(authenticationRequest.getUsername()); final String jwt = jwtUtil.generateToken(userDetails.getUsername()); return ResponseEntity.ok(new AuthenticationResponse(jwt)); } }
왜냐하면 사용자 인증을 처리하고 JWT 토큰을 발급해야만 안전한 인증을 구현할 수 있기 때문입니다.
권한 부여 설정
사용자 인증이 완료되면, 이제 권한 부여를 설정할 수 있습니다.
스프링 시큐리티를 사용하여 사용자 권한을 설정하고, 특정 API에 대한 접근을 제한합니다.
예를 들어, WebSecurityConfigurerAdapter를 확장하여 권한 부여 설정을 작성합니다:
@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtRequestFilter jwtRequestFilter; @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable() .authorizeRequests().antMatchers("/authenticate").permitAll() .anyRequest().authenticated(); httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); } }
그리고 JWT 필터를 작성하여 요청을 가로채고 JWT 토큰을 검증합니다:
@Component public class JwtRequestFilter extends OncePerRequestFilter { @Autowired private JwtUtil jwtUtil; @Autowired private UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization"); String username = null; String jwt = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); username = jwtUtil.extractUsername(jwt); } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if (jwtUtil.validateToken(jwt, userDetails)) { UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); } } chain.doFilter(request, response); } }
왜냐하면 권한 부여를 설정해야만 특정 API에 대한 접근을 제한할 수 있기 때문입니다.
테스트 및 검증
모든 설정이 완료되면, 이제 테스트 및 검증을 통해 구현한 기능이 정상적으로 동작하는지 확인합니다.
Postman과 같은 도구를 사용하여 인증 요청을 보내고, JWT 토큰을 발급받습니다.
발급받은 JWT 토큰을 사용하여 보호된 API에 접근하고, 권한 부여가 정상적으로 동작하는지 확인합니다.
예를 들어, Postman에서 다음과 같이 요청을 보낼 수 있습니다:
POST /authenticate { "username": "user", "password": "password" }
그리고 발급받은 JWT 토큰을 Authorization 헤더에 추가하여 보호된 API에 접근합니다:
GET /protected Authorization: Bearer
왜냐하면 테스트 및 검증을 통해 구현한 기능이 정상적으로 동작하는지 확인해야 하기 때문입니다.
결론
이번 글에서는 스프링 부트와 JWT를 활용하여 인증 및 권한 부여를 구현하는 방법에 대해 다루었습니다.
JWT 설정, 사용자 인증 구현, 권한 부여 설정, 테스트 및 검증 과정을 단계별로 설명했습니다.
스프링 부트와 JWT를 활용하면 안전하고 확장성이 뛰어난 인증 및 권한 부여 시스템을 구현할 수 있습니다.
왜냐하면 JWT는 안전하고 확장성이 뛰어난 인증 방법을 제공하기 때문입니다.
이 컨텐츠는 F-Lab의 고유 자산으로 상업적인 목적의 복사 및 배포를 금합니다.