๐Ÿ”‘ Spring Security - JWT ์ธ์ฆ ํ•„ํ„ฐ ๊ตฌํ˜„ํ•˜๊ธฐ

DUยท2025๋…„ 9์›” 5์ผ
0

๐Ÿ“Œ JWT ์ธ์ฆ ๊ณผ์ • ๊ฐœ์š”

Spring Security์—์„œ JWT(JSON Web Token) ์ธ์ฆ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

  1. ํด๋ผ์ด์–ธํŠธ ๋กœ๊ทธ์ธ ์š”์ฒญ โ†’ ์„œ๋ฒ„์—์„œ JWT ๋ฐœ๊ธ‰.
  2. ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ ์‹œ ํ—ค๋”์— JWT ํฌํ•จ (Authorization: Bearer <ํ† ํฐ>).
  3. ์„œ๋ฒ„์˜ ํ•„ํ„ฐ(JwtAuthenticationFilter)๊ฐ€ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„์„œ:
    • ํ—ค๋”์—์„œ ํ† ํฐ ์ถ”์ถœ
    • ์œ ํšจ์„ฑ ๊ฒ€์ฆ
    • ์‚ฌ์šฉ์ž ์ •๋ณด ๋กœ๋“œ
    • SecurityContext์— ์ธ์ฆ ๊ฐ์ฒด ์ €์žฅ
  4. ์ดํ›„ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @AuthenticationPrincipal ๋“ฑ์„ ํ†ตํ•ด ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํ™œ์šฉ.

์ด ํ•„ํ„ฐ๋Š” ๋ชจ๋“  HTTP ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„ JWT๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  ์ธ์ฆ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ“ ์ฝ”๋“œ ์ „์ฒด

package com.example.demo.security;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.*;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;

@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider jwt;
    private final UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws ServletException, IOException {

        // 1. ์š”์ฒญ ํ—ค๋”์—์„œ Authorization ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
        String header = req.getHeader("Authorization");

        // 2. "Bearer "๋กœ ์‹œ์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ
        if (header != null && header.startsWith("Bearer ")) {
            String token = header.substring(7);

            // 3. ํ† ํฐ ์œ ํšจ์„ฑ ๊ฒ€์ฆ
            if (jwt.validate(token)) {
                // 4. ํ† ํฐ์—์„œ ์‚ฌ์šฉ์ž ์ด๋ฆ„(username) ์ถ”์ถœ
                String username = jwt.getUsername(token);

                // 5. DB์—์„œ ์‚ฌ์šฉ์ž ์ •๋ณด ๋กœ๋“œ
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);

                // 6. ์‚ฌ์šฉ์ž ์ •๋ณด ๊ธฐ๋ฐ˜ ์ธ์ฆ ๊ฐ์ฒด ์ƒ์„ฑ
                UsernamePasswordAuthenticationToken auth =
                        new UsernamePasswordAuthenticationToken(
                                userDetails, null, userDetails.getAuthorities());

                // 7. SecurityContext์— ์ธ์ฆ ๊ฐ์ฒด ์ €์žฅ
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        }

        // 8. ๋‹ค์Œ ํ•„ํ„ฐ/์ปจํŠธ๋กค๋Ÿฌ๋กœ ์š”์ฒญ ์ „๋‹ฌ
        chain.doFilter(req, res);
    }
}

๐Ÿ” ์„ธ๋ถ€ ์„ค๋ช…

1. ํด๋ž˜์Šค ์„ ์–ธ๋ถ€

@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter
  • @Component: ์ด ํด๋ž˜์Šค๋ฅผ Spring Bean์œผ๋กœ ๋“ฑ๋กํ•˜์—ฌ Spring IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  • OncePerRequestFilter: ํ•œ ๋ฒˆ์˜ ์š”์ฒญ(request)์— ๋Œ€ํ•ด ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” ํ•„ํ„ฐ๋ฅผ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
  • @RequiredArgsConstructor: final ํ•„๋“œ(jwt, userDetailsService)๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ **์˜์กด์„ฑ ์ฃผ์ž…(DI)**์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

2. Authorization ํ—ค๋” ์ฒ˜๋ฆฌ

String header = req.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
    String token = header.substring(7);
}

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „์†กํ•œ HTTP ์š”์ฒญ์˜ Authorization ํ—ค๋”์—์„œ JWT๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ JWT๋Š” "Bearer <ํ† ํฐ๊ฐ’>" ํ˜•์‹์œผ๋กœ ์ „๋‹ฌ๋˜๋ฏ€๋กœ, "Bearer " ์ ‘๋‘์–ด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์ˆœ์ˆ˜ ํ† ํฐ ๊ฐ’๋งŒ ์–ป์Šต๋‹ˆ๋‹ค.

3. JWT ๊ฒ€์ฆ ๋ฐ ์‚ฌ์šฉ์ž ์ด๋ฆ„ ์ถ”์ถœ

if (jwt.validate(token)) {
    String username = jwt.getUsername(token);
}

**JwtTokenProvider**๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ† ํฐ์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ† ํฐ์ด ์œ ํšจํ•˜๋‹ค๋ฉด, ํ† ํฐ ๋‚ด์— ์ €์žฅ๋œ **์‚ฌ์šฉ์ž ์ด๋ฆ„(Subject)**์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

4. ์‚ฌ์šฉ์ž ์ •๋ณด ๋กœ๋“œ

UserDetails userDetails = userDetailsService.loadUserByUsername(username);

**UserDetailsService**๋Š” Spring Security์—์„œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ•ต์‹ฌ ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ถ”์ถœํ•œ ์‚ฌ์šฉ์ž ์ด๋ฆ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ๋‹ค๋ฅธ ์ €์žฅ์†Œ์—์„œ ์‚ฌ์šฉ์ž ๊ณ„์ • ์ •๋ณด๋ฅผ UserDetails ๊ฐ์ฒด๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

5. ์ธ์ฆ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐ SecurityContext ์ €์žฅ

UsernamePasswordAuthenticationToken auth =
        new UsernamePasswordAuthenticationToken(
                userDetails, null, userDetails.getAuthorities());

SecurityContextHolder.getContext().setAuthentication(auth);

**์ธ์ฆ ๊ฐ์ฒด(Authentication)**๋ฅผ ์ƒ์„ฑํ•˜๊ณ  SecurityContextHolder์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

  • ์ฒซ ๋ฒˆ์งธ ์ธ์ž: Principal (์‚ฌ์šฉ์ž ์ •๋ณด)
  • ๋‘ ๋ฒˆ์งธ ์ธ์ž: Credentials (๋น„๋ฐ€๋ฒˆํ˜ธ) - ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ์ด๋ฏ€๋กœ null๋กœ ์„ค์ • ๊ฐ€๋Šฅ.
  • ์„ธ ๋ฒˆ์งธ ์ธ์ž: Authorities (๊ถŒํ•œ ๋ชฉ๋ก)

์ด๋ ‡๊ฒŒ SecurityContextHolder์— ์ €์žฅ๋œ ์ธ์ฆ ์ •๋ณด๋Š” ์ดํ›„ ์ปจํŠธ๋กค๋Ÿฌ๋‚˜ ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ ์ „์—ญ์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โœ… ์ •๋ฆฌ / ๋ฐฐ์šด ์ 

  • JwtAuthenticationFilter๋Š” ๋ชจ๋“  ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„ JWT๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ํ•ต์‹ฌ ํ•„ํ„ฐ์ž…๋‹ˆ๋‹ค.
  • ์ธ์ฆ์— ์„ฑ๊ณตํ•˜๋ฉด SecurityContext์— ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜์—ฌ Spring Security ์ „์—ญ์—์„œ ์ธ์ฆ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ๋•๋ถ„์— ์ปจํŠธ๋กค๋Ÿฌ ๋‹จ์—์„œ๋Š” ๋ณ„๋„์˜ ์ธ์ฆ ๋กœ์ง ์—†์ด @AuthenticationPrincipal ๋“ฑ์„ ํ™œ์šฉํ•˜์—ฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด์— ์†์‰ฝ๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿš€ ํ™•์žฅ

  • ํ† ํฐ์ด ์œ ํšจํ•˜์ง€ ์•Š์„ ๋•Œ 401 Unauthorized ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•„ํ„ฐ๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Refresh Token๊ณผ Access Token์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋” ์•ˆ์ „ํ•œ ์ธ์ฆ ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋กœ๊ทธ์•„์›ƒ ์‹œ ํ† ํฐ์„ ๋ฌดํšจํ™”ํ•˜๋Š” JWT ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€