Contents
see List작성일 2025. 11. 30.
Spring Security 6 JWT 인증 구현
Spring Security 6에서 JWT 토큰 기반 인증을 구현하는 방법입니다.
의존성
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>Security 설정 (Spring Security 6)
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}JWT 유틸리티
@Component
public class JwtUtil {
private final String SECRET = "your-secret-key";
private final long EXPIRATION = 86400000; // 24시간
public String generateToken(UserDetails user) {
return Jwts.builder()
.subject(user.getUsername())
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(Keys.hmacShaKeyFor(SECRET.getBytes()))
.compact();
}
public String extractUsername(String token) {
return Jwts.parser()
.verifyWith(Keys.hmacShaKeyFor(SECRET.getBytes()))
.build()
.parseSignedClaims(token)
.getPayload()
.getSubject();
}
public boolean isTokenValid(String token, UserDetails user) {
String username = extractUsername(token);
return username.equals(user.getUsername()) && !isTokenExpired(token);
}
}JWT 필터
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
String username = jwtUtil.extractUsername(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails user = userDetailsService.loadUserByUsername(username);
if (jwtUtil.isTokenValid(token, user)) {
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
}
chain.doFilter(request, response);
}
}로그인 컨트롤러
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private AuthenticationManager authManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
Authentication auth = authManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getUsername(), request.getPassword()));
UserDetails user = (UserDetails) auth.getPrincipal();
String token = jwtUtil.generateToken(user);
return ResponseEntity.ok(Map.of("token", token));
}
}Refresh Token 구현
// Access Token: 15분
// Refresh Token: 7일
@PostMapping("/refresh")
public ResponseEntity<?> refresh(@RequestBody RefreshRequest request) {
String refreshToken = request.getRefreshToken();
if (jwtUtil.isRefreshTokenValid(refreshToken)) {
String username = jwtUtil.extractUsername(refreshToken);
UserDetails user = userDetailsService.loadUserByUsername(username);
String newAccessToken = jwtUtil.generateAccessToken(user);
return ResponseEntity.ok(Map.of("accessToken", newAccessToken));
}
return ResponseEntity.status(401).build();
}spring
| No | 작성일 | Title |
|---|---|---|
| 164 | 2015. 02. 24. | [ spring ] properties 동적으로 사용하기 (context:property-placeholder 및 util:properties) |
| 149 | 2015. 02. 16. | [ Spring Security ] 스프링 시큐리티 미세 접근 제한 |
| 148 | 2015. 02. 13. | [ Spring ] @Valid 어노테이션에 쉽게 매핑하기 |
| 145 | 2015. 01. 26. | [ Spring ] Transaction Isolation [ 트랜젝션 격리 ] 관리 |
| 109 | 2014. 12. 23. | [ spring ] transaction propagation [ 트랜젝션 전파 ] 관리 |
| 103 | 2014. 10. 29. | [ spring ] 스프링에서 스케줄링(Schedule) 등록하는 방법 |
| 44 | 2014. 09. 29. | [ spring security ] 스프링 시큐리티 xml 설정 |
| 43 | 2014. 09. 29. | [ spring security ] 스프링 시큐어리티 access 옵션 |
| 40 | 2014. 09. 29. | [ mybatis ] 마이바티스 map 이나 bean 을 이용하지 않고 2개이상 파라메터 전달하기 |
| 39 | 2014. 09. 26. | [ spring ] view(jsp) 에서 htmlEscape 사용하기 |