๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[Spring]/Spring Security

๋‹น์‹ ์˜ ์ฒซ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ(6) - ๋กœ๊ทธ์ธ ์‹œ JWT ๋ฐœ๊ธ‰๊ณผ redis ์ €์žฅ ๊ตฌํ˜„ํ•˜๊ธฐ

by ํŒกํŽ‘ํ 2025. 3. 9.
728x90
๐Ÿ“Œ ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ง€๋‚œ ์‹œ๊ฐ„์— ์ด์–ด ๋กœ๊ทธ์ธ ์‹œ jwt๋ฅผ ๋ฐœ๊ธ‰ํ•˜์—ฌ ์‘๋‹ต ํ—ค๋”์— ์‹ฃ๊ณ , ํ† ํฐ์„ redis์— ์ €์žฅํ•˜๋Š” ๊ณผ์ •์„ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿค— ์ €์˜ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ๊ตฌํ˜„์€ ์•„๋ž˜์™€ ๊ฐ™์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
- ํ”„๋ก ํŠธ ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๊ฐ€ ๋‚˜๋‰˜์–ด ์ง„ํ–‰๋˜๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์—ฌ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •์—์„œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์„ค์ •์„ ๋”ฐ๋กœ ํ•˜์ง€ ์•Š์Œ
- JWT ํ† ํฐ ์ธ์ฆ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•จ
- ํ† ํฐ ๊ด€๋ฆฌ์— redis๋ฅผ ์ด์šฉํ•จ

 

๐Ÿ™‰ ์ด์ „ ๊ธ€ ๋ณด๊ธฐ

์ฒซ ๋ฒˆ์งธ ๊ธ€๋ถ€ํ„ฐ ์ •๋…ํ•˜์‹œ๋ฉด ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

https://suzuworld.tistory.com/438 - ๋‹น์‹ ์˜ ์ฒซ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ํ†บ์•„๋ณด๊ธฐ

์ด์ „ ๊ธ€

https://suzuworld.tistory.com/446 - JwtTokenizer์™€ Redis ํด๋ž˜์Šค ์ž‘์„ฑํ•˜๊ธฐ 

 

๐Ÿ“– ๋ชฉ์ฐจ

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ํ†บ์•„๋ณด๊ธฐ

SecurityConfig ๊ตฌ์„ฑํ•˜๊ธฐ

์ธ์ฆ ๋ฐฉ์‹ ๊ฐœ๋…๊ณผ AuthenticationFilter 

AuthenticationManager, AuthenticationProvider, UserDetailsService, UserDetails

๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ ๋ฐ JWT, redis ๊ฐœ๋… ์ •๋ฆฌ

JwtTokenizer์™€ Redis ํด๋ž˜์Šค ์ž‘์„ฑํ•˜๊ธฐ

๋กœ๊ทธ์ธ ์‹œ JWT ๋ฐœ๊ธ‰๊ณผ redis ์ €์žฅ ๊ตฌํ˜„ํ•˜๊ธฐ (ํ˜„์žฌ ๊ธ€)

 

๐Ÿ‘ฃ ์ง€๋‚œ ์‹œ๊ฐ„๊นŒ์ง€์˜ ๋‚ด์šฉ ์ •๋ฆฌ

  • ์šฐ๋ฆฌ๋Š” ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ตฌํ˜„ํ•œ ๋กœ๊ทธ์ธ ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    • ํด๋ผ์ด์–ธํŠธ(web, app)์—์„œ ์ž…๋ ฅ๋ฐ›์€ id, password๊ฐ€ http ์š”์ฒญ ๋ฐ”๋””์— ์‹ค๋ ค ์„œ๋ฒ„๋กœ ๋„˜์–ด์˜ฌ ๋•Œ ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ(AuthenticationFilter)์— ์˜ํ•ด ํ•„ํ„ฐ๋ง๋˜์–ด ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ๊ฐ€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.
    • ์ดํ›„ AuthenticationManager, AuthenticationProvider, UserDetailsService๋ฅผ ๊ฑฐ์ณ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‚ด์— ์žˆ๋Š” id, password์™€ ๋น„๊ต๋ฅผ ํ•˜์—ฌ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ๋กœ๊ทธ์ธ ์‹œ ์ž…๋ ฅ๋ฐ›์€ id, password์™€, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‚ด id, password๋ฅผ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋กœ๊ทธ์ธ์ด ์„ฑ๊ณตํ–ˆ๋‹ค!, ์‹คํŒจํ–ˆ๋‹ค! ์ด ์™ธ์— ์–ด๋–ค ์ž‘์—…๋„ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ ์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด๋‚ผ ์‘๋‹ต ํ—ค๋”์— access token๊ณผ refresh token์„ ์‹ค์–ด ๋ณด๋‚ด๊ณ , redis์— ํ† ํฐ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ถ€๋ถ„์„ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

์ง€๋‚œ ์‹œ๊ฐ„๊นŒ์ง€์˜ ํฌ์ŠคํŠธ๋งจ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต ์˜ˆ์‹œ

 

์„œ๋ฒ„ ๋กœ๊ทธ

  • ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋ฐ”์™€ ๊ฐ™์ด ์ง€๋‚œ ์‹œ๊ฐ„๊นŒ์ง€์˜ ๊ตฌํ˜„์€ ๊ทธ์ € ๋กœ๊ทธ๋กœ ์„ฑ๊ณต๊ณผ ์‹คํŒจ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ ์™ธ์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” ๋ฐ”๋กœ ์ด์ „ ๊ธ€์— JwtTokeninzer ํด๋ž˜์Šค์™€, redis ๊ด€๋ จ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ™‚ ์ง€๋‚œ ์‹œ๊ฐ„๊นŒ์ง€์˜ ๋กœ๊ทธ์ธ ๊ตฌํ˜„ ๋‚ด์šฉ  ๊ฐ„๋‹จ ๋ณต์Šต

JwtAuthenticationFilter

  • ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑˆ ํ•„ํ„ฐ์—์„œ ๋กœ๊ทธ์ธ DTO๋ฅผ ์ƒ์„ฑํ•˜์—ฌ AuthenticationManager์—๊ฒŒ ๋กœ๊ทธ์ธ ์œ„์ž„์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

SecurityConfig

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    ...
 
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        // ๋กœ๊ทธ์ธ ํ•„ํ„ฐ
        JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
        jwtAuthenticationFilter.setFilterProcessesUrl("/login");
        jwtAuthenticationFilter.setAuthenticationSuccessHandler(new MemberAuthenticationSuccessHandler());
        jwtAuthenticationFilter.setAuthenticationFailureHandler(new MemberAuthenticationFailureHandler());
        ...
        
     }
}
  • ์œ„์˜ JwtAuthenticationFilter๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ์˜ ๋กœ๊ทธ์ธ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” SecurityConfig ํด๋ž˜์Šค์—์„œ "/login"์ด๋ผ๋Š” ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋กœ๊ทธ์ธ์šฉ ์—”๋“œํฌ์ธํŠธ๋กœ ์„ค์ •ํ•ด ๋’€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ์ดํ›„ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋‚ด๋ถ€์ ์œผ๋กœ ์„ฑ๊ณต ์‹œ์—๋Š” SuccessHandler๋กœ, ์‹คํŒจ ์‹œ์—๋Š” FailureHandler๋กœ ๊ฐ€๋„๋ก ์„ค์ •ํ•ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

 

MemberAuthenticationSuccessHandler

@Slf4j
public class MemberAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        log.info("๋กœ๊ทธ์ธ ์„ฑ๊ณต!");
    }
}

 

MemberAuthenticationFailureHandler

@Slf4j
public class MemberAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {
        log.info("๋กœ๊ทธ์ธ ์‹คํŒจ!");
    }
}

 

์„œ๋ฒ„ ๋กœ๊ทธ

 

  • ์œ„ ๋‘ ํ•ธ๋“ค๋Ÿฌ์— ์˜ํ•ด ๋กœ๊ทธ๊ฐ€ ๋‚จ์•˜๋˜ ๊ฒƒ์ด์ฃ .
  • ์ด ๋‘ ๋™์ž‘ ์™ธ์— ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ์–ด๋– ํ•œ ๋ณ€ํ™”๋„ ์—†๋Š” ๊ฒƒ์ด ํ˜„์žฌ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

 

โ˜๐Ÿป ํ•ด์•ผ ํ•  ์ผ

 ์ด์ œ๋ถ€ํ„ฐ๋Š” ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ์—๋Š” jwt๋ฅผ ๋ฐœ๊ธ‰ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•˜๊ณ , redis์— ํ† ํฐ์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

JwtAuthenticationFilter ์ˆ˜์ •

  • ๊ธฐ์กด JwtAuthenticationFilter์— successfulAuthentication ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

 

  • ์ธํ…”๋ฆฌ์ œ์ด์—์„œ Mac ๊ธฐ์ค€ cmd + n ๋ช…๋ น์–ด๋กœ ์‰ฝ๊ฒŒ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

AbstractAuthenticationProcessingFilter

  • successfulAuthentication ๋ฉ”์„œ๋“œ๋Š” AbstractAuthenticationProcessingFilter์—์„œ ๊ตฌํ˜„๋œ ๋ฉ”์„œ๋“œ๋กœ ์ธ์ฆ ์„ฑ๊ณต ์‹œ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

SecurityConfig ์ˆ˜์ •

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    private final JwtTokenizer jwtTokenizer; // ์ถ”๊ฐ€
    private final RedisService redisService; // ์ถ”๊ฐ€
    ...
 
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        // ๋กœ๊ทธ์ธ ํ•„ํ„ฐ
        JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager(), jwtTokenizer, redisService); // ์ˆ˜์ •
        jwtAuthenticationFilter.setFilterProcessesUrl("/login");
        jwtAuthenticationFilter.setAuthenticationSuccessHandler(new MemberAuthenticationSuccessHandler());
        jwtAuthenticationFilter.setAuthenticationFailureHandler(new MemberAuthenticationFailureHandler());
        ...
        
     }
}
  • SpringConfig์— JwtTokenizer์™€ RedisService๋ฅผ ์˜์กด์„ฑ ์ถ”๊ฐ€ํ•˜๊ณ ,
  • new ํ‚ค์›Œ๋“œ๋กœ ์ƒ์„ฑํ•  JwtAuthenticationFilter ํŒŒ๋ผ๋ฏธํ„ฐ์— jwtTokenizer์™€ redisService๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

 

JwtAuthenticationFilter ์ˆ˜์ •

  • JwtAuthenticationFilter ํด๋ž˜์Šค์— ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ JwtTokenizer์™€ RedisService ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • ๋˜ํ•œ, successfulAuthentication์—์„œ ์ธ์ฆ ์„ฑ๊ณต ํ›„ Jwt๋ฅผ ๋ฐœ๊ธ‰ํ•˜์—ฌ ์‘๋‹ต ํ—ค๋”์— ์‹ฃ๊ณ , redis์— refresh token์„ ์ €์žฅํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฐธ๊ณ ๋กœ ์œ„ ์ฝ”๋“œ๋Š” log.debug๋กœ ์„ค์ •ํ–ˆ๋Š”๋ฐ log.info๋กœ ๋ณ€๊ฒฝํ•˜์‹œ๋ฉด ๋ณ„๋„์˜ yaml ํŒŒ์ผ ์„ค์ • ์—†์ด ๋กœ๊ทธ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ‘จ๐Ÿปโ€๐Ÿ”ฌ successfulAuthentication ๋ฉ”์„œ๋“œ ์ƒ์„ธ ์„ค๋ช…

MemberDetailsService

  • ์ง€๋‚œ ์‹œ๊ฐ„ ๊ตฌํ˜„ํ•œ MemberDetailsService ํด๋ž˜์Šค์˜ loadUserByUsername ๋ฉ”์„œ๋“œ๋ฅผ ๋ณด์‹œ๋ฉด ์•„์‹œ๊ฒ ์ง€๋งŒ, UserDetails์˜ ๊ตฌํ˜„์ฒด์ธ MemberDetails๋ฅผ ๋ฆฌํ„ดํ•˜๊ธฐ ๋•Œ๋ฌธ์— successfulAuthentication์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ authResult์— MemberDetails๊ฐ€ ํฌํ•จ๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

Member ๊ฐ์ฒด๋กœ ์บ์ŠคํŒ…

Member member = (Member) authResult.getPrincipal();
  • MemberDetails๋Š” Member์˜ ์ž์‹ ํด๋ž˜์Šค์ž„์œผ๋กœ ์œ„์™€ ๊ฐ™์ด Member๋กœ ์บ์ŠคํŒ… ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™(LSP)์ด ์—ฌ๊ธฐ์„œ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

 

createAccessToken & RefreshToken

String accessToken = jwtTokenizer.createAccessToken(member);
String refreshToken = jwtTokenizer.createRefreshToken(member);

  • ์ดํ›„ Member ๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ•˜์—ฌ AccessToken๊ณผ RefreshToken์„ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.
    • ์ž์„ธํ•œ ๋กœ์ง์€ ์ง€๋‚œ ์‹œ๊ฐ„ ๋ฉ”์„œ๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ๋”ฐ๋ผ๊ฐ€ ๋ณด์„ธ์š”.

 

setRefreshToken

redisService.setRefreshToken(member.getMemberId(), refreshToken, jwtTokenizer.getRefreshTokenExpirationMinutes());

  • ๋ฐœ๊ธ‰ํ•œ refresh token์„ redis์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

 

ValueOperations<K, V>

default void set(K key, V value, Duration timeout)
  • redis์— key๋กœ๋Š” refresh token, value๋กœ๋Š” member์˜ memberId(id)๋ฅผ ์ €์žฅํ•˜๋ฉฐ ์ž์ฒด์ ์œผ๋กœ timeout ์‹œ๊ฐ„์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ด๋กœ์จ refreshToken์„ ๊ฒ€์ฆ์— ์‚ฌ์šฉํ•  ๋•Œ ์œ ์ €์˜ refresh token(key)์„ ํ†ตํ•ด id(value)์„ ๊บผ๋‚ด์–ด ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
    • timeout์ด ์„ค์ •๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด redis์—์„œ ์ž์ฒด์ ์œผ๋กœ ์‚ญ์ œํ•˜์—ฌ ์‹œ๊ฐ„์ด ๋งŒ๋ฃŒ๋œ ํ† ํฐ์€ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

redis์— refresh token๋งŒ ์ €์žฅํ•˜๋Š” ์ด์œ ?

  1. Access Token์€ ์ž์ฒด์ ์œผ๋กœ ๊ฒ€์ฆ ๊ฐ€๋Šฅ โ†’ ์„œ๋ฒ„์—์„œ JWT์˜ ์„œ๋ช…์„ ํ™•์ธํ•˜๋ฉด ๊ฒ€์ฆ ๋ (DB ์กฐํšŒ ๋ถˆํ•„์š”).
  2. Refresh Token์€ ์„œ๋ฒ„์—์„œ ๊ด€๋ฆฌ ํ•„์š” โ†’ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•ด ์ €์žฅํ•˜๊ณ  ๋งŒ๋ฃŒ/๋กœ๊ทธ์•„์›ƒ ์‹œ ์‚ญ์ œ ๊ฐ€๋Šฅ.
  3. ๋ณด์•ˆ ๊ฐ•ํ™” โ†’ Refresh Token์„ ํƒˆ์ทจ๋‹นํ•˜๋ฉด ์œ„ํ—˜ํ•˜๋ฏ€๋กœ Redis์—์„œ ๊ด€๋ฆฌํ•˜์—ฌ ์ฆ‰์‹œ ๋ฌดํšจํ™” ๊ฐ€๋Šฅ.
  4. ํšจ์œจ์„ฑ โ†’ Access Token๊นŒ์ง€ Redis์— ์ €์žฅํ•˜๋ฉด ์š”์ฒญ๋งˆ๋‹ค ์กฐํšŒํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋ถˆํ•„์š”ํ•œ ๋ถ€ํ•˜ ๋ฐœ์ƒ.

์ฆ‰, Access Token์€ ๊ฒ€์ฆ๋งŒ ํ•˜๋ฉด ๋˜๊ณ , Refresh Token์€ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Redis์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์‘๋‹ต ํ—ค๋”์— ์‹ฃ๊ณ  ์„ฑ๊ณต ํ•ธ๋“ค๋Ÿฌ ํ˜ธ์ถœ

response.addHeader("Authorization", "Bearer " + accessToken);
response.addHeader("Refresh", refreshToken);

this.getSuccessHandler().onAuthenticationSuccess(request, response, authResult);
  • redis๊นŒ์ง€ ์ €์žฅํ•˜๊ณ  ๋‚˜๋ฉด, ์ด์ œ ์‘๋‹ต ํ—ค๋”์— ํ† ํฐ์„ ์‹ฃ๊ณ  successHandler๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋•Œ, AccessToken์— Bearer๋ฅผ ๋ถ™์ด๋Š” ์ด์œ ๋Š” OAuth 2.0 ๊ธฐ๋ฐ˜์˜ JWT ๋“ฑ์˜ ์ธ์ฆ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ๊ด€๋ก€๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

๐Ÿ‘จ๐Ÿปโ€๐Ÿ”ฌ ๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ

  • ํฌ์ŠคํŠธ๋งจ์œผ๋กœ ํšŒ์›๊ฐ€์ž…์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

  • ๊ทธ๋‹ค์Œ ๋กœ๊ทธ์ธ API๋ฅผ ์ด์šฉํ•˜์—ฌ ๋กœ๊ทธ์ธํ•ด ๋ด…๋‹ˆ๋‹ค.
  • ์ •์ƒ์ ์œผ๋กœ ๋กœ๊ทธ์ธ์ด ์ง„ํ–‰๋˜๋ฉฐ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์‘๋‹ต ํ—ค๋”์— AccessToken(Authorization), RefreshToken(Refresh)๊ฐ€ ์‹ค๋ฆฐ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿš€ redis ๋‚ด ์ €์žฅ๋œ refreshToken ํ™•์ธํ•˜๊ธฐ

// ์„œ๋ฒ„ ๋กœ๊ทธ(log.debug๋กœ ์ฐํžŒ ๋กœ๊ทธ)
// debug ๋กœ๊ทธ๋ฅผ ๋ณด๋ ค๋ฉด yaml ํŒŒ์ผ์—์„œ ๋ณ„๋„์˜ ์ˆ˜์ • ํ•„์š”!
[ JwtAuthenticationFilter - successfulAuthentication ] refreshToken : 
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiLtmY3quLjrj5kiLCJpYXQiOjE3NDE1MjY5OTMsImV4cCI6MTc0MTUzMDU5M30.wcyAmL-ZL0_wN_VQ62iXJEBJ9gleDnOp0R7sA9U3INM

// docker ๋‚ด redis ์ ‘์†ํ•˜๊ธฐ
$ docker ps

// docker ps๋กœ redis ์ปจํ…Œ์ด๋„ˆ id or name ํ™•์ธํ•˜์—ฌ ์ ‘์†
$ docker exec -it <container id or name> redis-cli

// key(memberId)๋กœ value(refresh token) ๊ฐ€์ ธ์˜ค๊ธฐ
127.0.0.1:6379> get "aaa"
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiLtmY3quLjrj5kiLCJpYXQiOjE3NDE1MjY5OTMsImV4cCI6MTc0MTUzMDU5M30.wcyAmL-ZL0_wN_VQ62iXJEBJ9gleDnOp0R7sA9U3INM"
  • redis์— ์ ‘์†ํ•˜์—ฌ refreshToken์ด ์ •์ƒ์ ์œผ๋กœ ์ €์žฅ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿฅธ ๋‹ค์Œ ์‹œ๊ฐ„

  • ์ด์ œ ๊ฑฐ์˜ ๋์ด ๋ณด์ž…๋‹ˆ๋‹ค.
  • ํ•ด๋‹น AccessToken์œผ๋กœ ๋ณด์•ˆ ์š”์ฒญ์„ ์‹คํ–‰ํ•˜๋Š” ๋กœ์ง, ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์žฌ๋ฐœํ–‰ํ•˜๋Š” ๋กœ์ง, ๋งˆ์ง€๋ง‰์œผ๋กœ ๋กœ๊ทธ์•„์›ƒ ํ•˜๋Š” ๋กœ์ง์„ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
728x90