ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Security + JWT ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ (2)
    Spring 2022. 10. 23. 16:13
    ๋ฐ˜์‘ํ˜•

    ๐ŸŽˆ ์ง€๋‚œ ๊ฒŒ์‹œ๊ธ€์—์„  Spring Security์˜ ๊ตฌ์กฐ์™€ ํ•„์š”ํ•œ Settings์„ ๋‹ค๋ค˜์Šต๋‹ˆ๋‹ค.
    ์ด์–ด์„œ Security์— ํ•„์š”ํ•œ Class๋“ค์„ ๋‹ค๋ค„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    ์ง€๋‚œ ํฌ์ŠคํŒ…์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ์กฐ ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

    https://developer-been.tistory.com/2

     

    Spring Security + JWT ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ (1)

    ํ•ด๋‹น ํฌ์ŠคํŒ…์€ Spring Secuiry + JWT + JPA ๋ฅผ ์ด์šฉํ•ด ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ ๊ด€๋ จ ์˜ˆ์ œ ์ž…๋‹ˆ๋‹ค. ํ™˜๊ฒฝ : Spring boot(2.5.5) + Mysql Spring Security ์˜์—ญ ์ธ์ฆ(Authentication)๊ณผ ๊ถŒํ•œ(Authorization) ์ธ์ฆ(Authentication) : ๋ณดํ˜ธ๋œ ๋ฆฌ

    developer-been.tistory.com

     

     


    ๐Ÿ“Œ ์ธ์ฆ ๊ตฌ์กฐ ์ˆœ์„œ

    1๏ธโƒฃ (Login → Jwt Token ๋ฐœ๊ธ‰๋œ ์ƒํƒœ) API ์š”์ฒญ
    2๏ธโƒฃ WebSecurityConfig์—์„œ configure์— addFilterBefore()๋กœ ์„ค์ •ํ•œ
    Authentication Filter ์ ‘๊ทผ
    3๏ธโƒฃ JwtAuthenticationFilter → Jwt Token ๊ฒ€์ฆ
    4๏ธโƒฃ ๊ฒ€์ฆ์ด ์™„๋ฃŒ ๋ฌ๋‹ค๋ฉด, getAuthentication()์„ ํ†ตํ•ด์„œ UserDetailService ์‹คํ–‰
    → DB์—์„œ member ์กฐํšŒ→ Security์˜ User๊ฐ์ฒด๋ฅผ ์ƒ์†๋ฐ›์€ MemberAccount ๊ฐ์ฒด return
    5๏ธโƒฃ ์œ„ ๊ณผ์ • ํ†ตํ•ด UsernamePasswordAuthenticationToken ์ƒ์„ฑ ํ›„,
    SecurityContextHolder์˜ context์— Authentication์„ Set.
    6๏ธโƒฃ DispatcherServlet ์ „๋‹ฌ

     


    ์‹œ์ž‘ํ•˜๊ธฐ

     

    ๐Ÿ“Œ MemberAccount.java

    @Getter
    @EqualsAndHashCode(callSuper =false)
    public class MemberAccount extends User {
    
    private Member member;
    
    public MemberAccount(Member member) {
    	super(member.getPhoneNum(), member.getPassword(), Collections.singletonList
    			 (newSimpleGrantedAuthority(member.getRoles().get(0))));
    	this.member = member;
      }
    }
    • Member์˜ Adapter Class
    • @AuthenticationPrincipal ๋ฅผ ํ†ตํ•ด(SpEL) Principal ๋‚ด๋ถ€ ์ •๋ณด์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member")
      -> ์ต๋ช… ์‚ฌ์šฉ์ž์ธ ๊ฒฝ์šฐ์—” null ๋ฆฌํ„ด
      -> ์ธ์ฆ๋œ ์ฃผ์ฒด์ธ ๊ฒฝ์šฐ member ๊ฐ์ฒด ๋ฆฌํ„ด

    ๐Ÿ’ก ์ฆ‰, Principal์˜ ๋‚ด๋ถ€ ์ •๋ณด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” Custom Anotation ์ƒ์„ฑ ์œ„ํ•œ Adapter Class

     


    ๐Ÿ“Œ CustomUserDetails Class ์ƒ์„ฑ (CustomUserDetails.java)

    @RequiredArgsConstructor
    @Service
    public class CustomUserDetailService implements UserDetailsService {
    
        private final MemberRepository memberRepository;
    
        @Override
        public UserDetails loadUserByUsername(String phoneNum) throws UsernameNotFoundException {
            Member member = memberRepository.findByPhoneNum(phoneNum)
                    .orElseThrow(() -> new UsernameNotFoundException("์‚ฌ์šฉ์ž๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."));
    
            return new MemberAccount(member);
        }
    }
    • Security์˜ UserDetailsService๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค. (UserService๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ์‰ฌ์›€)
    • loadUserByUsername() : DB์—์„œ ์œ ์ € ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์š”ํ•œ ์˜ค๋ฒ„๋ผ์ด๋“œ ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค.
    • ๋งŒ์•ฝ ํ•ด๋‹น username์˜ ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ์—†๋‹ค๋ฉด UsernameNotFoundException ์˜ˆ์™ธ๋ฅผ ๋˜์ ธ์ค๋‹ˆ๋‹ค.

    ๐Ÿ’ก MemberAccount(Free Naming)๋ฅผ return ํ•˜๋Š” ์ด์œ 
    → Spring Security๊ฐ€ ๋‹ค๋ฃจ๋Š” ์œ ์ € ์ •๋ณด์™€ ๋„๋ฉ”์ธ์—์„œ ๋‹ค๋ฃจ๋Š” ์œ ์ € ์ •๋ณด ์‚ฌ์ด ๊ฐญ์„ ๋งค๊ฟ”์ฃผ๋Š” ์ผ์ข…์˜ ์–ด๋Œ‘ํ„ฐ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.


    ๐Ÿ“Œ JWT ๊ฒ€์ฆ ํ•„ํ„ฐ ์ •์˜ (JwtAuthenticationFilter.java)

    @RequiredArgsConstructor
    public class JwtAuthenticationFilter extends GenericFilterBean {
    
    private final JwtTokenProvider jwtTokenProvider;
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
          // 1๏ธโƒฃ ํ—ค๋”์—์„œ JWT ๋ฐ›์•„์˜ค๊ธฐ
          String accessToken = jwtTokenProvider.resolveToken((HttpServletRequest) request);
    
          // 2๏ธโƒฃ ์œ ํšจ ํ† ํฐ ๊ฒ€์ฆ
          if (accessToken !=null && jwtTokenProvider.validateToken(accessToken, (HttpServletRequest) request)) {
                  // 3๏ธโƒฃ ํ† ํฐ ์œ ํšจ์‹œ ์œ ์ € ์ •๋ณด ๋ฐ›์•„์˜ค๊ธฐ
                  Authentication authentication = jwtTokenProvider.getAuthentication(accessToken);
    
                  // 4๏ธโƒฃ SecurityContext์— Authentication ๊ฐ์ฒด๋ฅผ ์ €์žฅ
                  SecurityContextHolder.getContext().setAuthentication(authentication);
          }
    
       5๏ธโƒฃ chain.doFilter(request, response);
     
       }
    }
    • ํ•ด๋‹น ํด๋ž˜์Šค๋Š” Custom AuthenticationFilter ์ž…๋‹ˆ๋‹ค. (Servlet๋‹จ์—์„œ ์ฒ˜๋ฆฌ)
    • GenericFilterBean์„ ์ƒ์† ๋ฐ›์€ Filter Class ์ƒ์„ฑ
    • ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•œ doFilter ํ•จ์ˆ˜ ์ •์˜
    • ์ตœ์ข…์ ์œผ๋กœ 5๏ธโƒฃ chain.doFilter() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด DispatcherServlet์œผ๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

    ๐Ÿ“Œ JwtTokenProvider Class ์ƒ์„ฑ (JwtTokenProvider.java)

    • ์„ธ์…˜-์ฟ ํ‚ค ๊ธฐ๋ฐ˜์˜ ๋ฐฉ์‹์ด ์•„๋‹Œ, JWT๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ† ํฐ ๋ฐœํ–‰,๊ฒ€์ฆ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“ˆ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • Jwt ์ƒ์„ฑ, ๊ฒ€์ฆ ๋“ฑ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•œ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ
    • ์•„๋ž˜ ๋ช…์‹œํ•œ 1๏ธโƒฃ~7๏ธโƒฃ๋ฒˆ ํ•จ์ˆ˜๋“ค ์ •์˜
    @Slf4j
    @RequiredArgsConstructor
    @Component
    public class JwtTokenProvider {
    
    // ๋ณด์•ˆ์„ ์œ„ํ•ด appplication.properties์— ์ €์žฅํ•œ key
    @Value("${project.jwt.access-token-key}") 
    privateString accessTokenKey;
    
    private final CustomUserDetailService userDetailsService;
    private final MemberRepository memberRepository;
    private final TokenRepository tokenRepository;
    
    
    // ์œ ํšจ์‹œ๊ฐ„ : AccessToken: 5๋ถ„ / RefreshToken: 7์ผ ์„ค์ •.
    private longACCESS_TOKEN_EXPIRE_TIME = 5 * 60 * 1000L;
    private longREFRESH_TOKEN_EXPIRE_TIME = 60 * 60 * 24 * 7 * 1000L;
    
    @PostConstruct
    protected void init() {
            accessTokenKey = Base64.getEncoder().encodeToString(accessTokenKey.getBy
    				tes(StandardCharsets.UTF_8));
    }
    
    ... ์•„๋ž˜์— ์ˆœ์ฐจ์ ์œผ๋กœ ๋ช…์‹œํ•œ ํ•จ์ˆ˜๋“ค ์ •์˜
    
    }
    • AccessToken Expired Time : 5๋ถ„ / RefreshToken Expired Time : 7์ผ ์„ค์ •
    • accessTokenkey๋ฅผ Base64๋กœ ์ธ์ฝ”๋”ฉ

     

    ๐Ÿ’ก @PostConstruct

    ๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™” ๋ถ€๋ถ„

    ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ ํ›„ ๋ณ„๋„์˜ ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์œ„ํ•ด ์‹คํ–‰ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธํ•œ๋‹ค.

    @PostConstruct ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ค์ •ํ•ด๋†“์€ init ๋ฉ”์†Œ๋“œ๋Š” WAS๊ฐ€ ๋„์›Œ์งˆ ๋•Œ ์‹คํ–‰๋œ๋‹ค.


    1๏ธโƒฃ JWT ๋ฐœ๊ธ‰ (JwtTokenProvider.java)

    public JwtTokensVO createToken(String userPk, List<String> roles) {
    
      // Header ๋ถ€๋ถ„ ์„ค์ •
      Map<String, Object> headers = new HashMap<>();
      headers.put("typ", "JWT");
      headers.put("alg", "HS256");
    
      // ํ† ํฐ Builder
      Claims claims = Jwts.claims().setSubject(userPk); // JWT payLoad์— ์ €์žฅ๋˜๋Š” ์ •๋ณด๋‹จ์œ„
      claims.put("roles", roles); // key, value ์Œ์œผ๋กœ ์ •๋ณด ์ €์žฅ
    
      Date now = new Date();
    
      Date accessDate = new Date(now.getTime() + ACCESS_TOKEN_EXPIRE_TIME);
      Date refreshDate = new Date(now.getTime() + REFRESH_TOKEN_EXPIRE_TIME);
    
      return JwtTokensVO.builder()
                .accessToken(generateToken(headers, claims, now, accessDate))
                .refreshToken(generateToken(headers, claims, now, refreshDate))
                .accessTokenExpirationDate(accessDate)
                .refreshTokenExpirationDate(refreshDate)
                .build();
    }
    • Header : HS256 ์•”ํ˜ธํ™” ๋ฐฉ์‹์˜ JWT ๋ช…์‹œ
    • Claims : subject(ํ† ํฐ ์ œ๋ชฉ)์— userPk ์ €์žฅ → ์—ฌ๊ธฐ์„œ๋Š” ๋กœ๊ทธ์ธ ์•„์ด๋”” (ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ)
    • roles : ์‚ฌ์šฉ์ž ๊ถŒํ•œ ์ €์žฅ
    • AccessToken : 5๋ถ„ | RefreshToken : 7์ผ
    • JwtTokensVO ํด๋ž˜์Šค build

    2๏ธโƒฃ JWT ์ƒ์„ฑ (JwtTokenProvider.java)

    public String generateToken(Map<String, Object> headers, Claims claims, Date now, Date expirationDt) {
    
      return Jwts.builder()
              .setHeader(headers)
              .setClaims(claims)// ์ •๋ณด ์ €์žฅ
              .setIssuedAt(now)// ํ† ํฐ ๋ฐœํ–‰ ์‹œ๊ฐ„ ์ •๋ณด
              .setExpiration(expirationDt)// set Expire Time
              .signWith(SignatureAlgorithm.HS256, accessTokenKey)// set algorithm, signature secret ๊ฐ’
              .compact();
    }
    • accessToken, refreshToken ์ƒ์„ฑ์„ ์œ„ํ•ด ๊ณตํ†ต ์ฒ˜๋ฆฌํ•œ ํ•จ์ˆ˜

    3๏ธโƒฃ JWT์—์„œ ํšŒ์› ์ •๋ณด ์ถ”์ถœ (JwtTokenProvider.java)

    public String getUserPk(String token) {
    	return Jwts.parser().setSigningKey(accessTokenKey).parseClaimsJws(token).getBo
    	dy().getSubject();
    }
    • accessTokenKey๋กœ ์„œ๋ช…, token value๋กœ Claims์˜ subject ๊ฐ’(์ €์žฅํ•ด๋‘” ๋กœ๊ทธ์ธ ์•„์ด๋””) return

    4๏ธโƒฃ JWT ํ† ํฐ์—์„œ ์ธ์ฆ ์ •๋ณด ์กฐํšŒ (JwtTokenProvider.java)

    public Authentication getAuthentication(String token) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(this.getUser      
        Pk(token));
        
        return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
    }
    • UserDetailService์˜ loadUserByUsername ๋ฉ”์„œ๋“œ์˜ ์ธ์ž๋กœ getUser(String token) ํ•จ์ˆ˜ ํ˜ธ์ถœ
    • UsernamePasswordAuthenticationToken return

    5๏ธโƒฃ Request Header์—์„œ Token ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ (JwtTokenProvider.java)

    public String resolveToken(HttpServletRequest request) {
      return request.getHeader("X-AUTH-TOKEN");
    }
    • API ์š”์ฒญ์‹œ Header์— Token์„ ๋‹ด์•„์„œ ์š”์ฒญ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    • “X-AUTH-TOKEN” : “TOKEN VALUE” ํ˜•์‹์ผ ๋•Œ, “X-AUTH-TOKEN” ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

    6๏ธโƒฃ ํ† ํฐ์œ ํšจ์„ฑ + ๋งŒ๋ฃŒ์ผ์ž ํ™•์ธ (JwtTokenProvider.java)

    public boolean validateToken(String jwtToken, HttpServletRequest request) {
    
      try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(accessTokenKey).parseClaimsJws(jwtToken);
            return !claims.getBody().getExpiration().before(new Date());
        } catch (SignatureException ex) {
            log.error("Invalid JWT Signature");
            request.setAttribute("exception", "invalidSignature");
            return false;
        } catch (MalformedJwtException ex) {
            log.error("Invalid JWT token");
            request.setAttribute("exception", "invalidJwt");
            return false;
        } catch (ExpiredJwtException ex) {
            log.error("Expired JWT token");
            request.setAttribute("exception", "expiredJwt");
            return false;
        } catch (UnsupportedJwtException ex) {
            log.error("Unsupported JWT exception");
            request.setAttribute("exception", "unsupportedJwt");
            return false;
        } catch (IllegalArgumentException ex) {
            log.error("Jwt claims string is empty");
            request.setAttribute("exception", "claimsEmpty");
            return false;
        }
    }
    • accessTokenKey๋กœ ์„œ๋ช…, token value๋กœ ์กฐํšŒํ•œ Claims์˜ ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ํ˜„์žฌ๋‚ ์งœ์™€ ๋น„๊ต
    • Jwt ๊ด€๋ จ Exception ๋ฐœ์ƒ์‹œ Filter์—์„œ ๋ฐœ์ƒํ•œ Exception์€ Spring์˜ DispatcherServlet๊นŒ์ง€ ๋‹ฟ์„ ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž ์ •์˜ Exception์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

    ๐Ÿ’ก JWT ๊ด€๋ จ Exception ๋ชฉ๋ก

    SignatureException : Invalid Signature

    MalformedJwtException : Invalid JWT

    ExpiredJwtException : Expired JWT

    UnsupportedJwtException : Unsupported Exception

    IllegalArgumentException : Empty JWT Claims stirng

     

    *** ํ•ด๊ฒฐ ๋ฐฉ์•ˆ (ํ•ด๋‹น ๋ถ€๋ถ„์€ ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.) ***

    • ์—๋Ÿฌ ๋ฐœ์ƒ์‹œ request์˜ attribute์— ๊ฐ ์—๋Ÿฌ ์ •๋ณด Set
    • Security Config ๋ถ€๋ถ„์— ์„ค์ •ํ•œ EntryPoint → customAuthenticationEntryPoint์—์„œ ํ•ธ๋“ค๋ง

    7๏ธโƒฃ Access Token ๊ฐฑ์‹  (JwtTokenProvider.java)

    public BaseResDto refreshAccessToken(HttpServletRequest request, String refreshToken) throws ServiceException {
    
    	if (validateToken(refreshToken, request)) {
            	String phoneNum = getUserPk(refreshToken);
    	        Member member = memberRepository.findByPhoneNum(phoneNum)
    	                	.orElseThrow(() -> new ServiceException(ResultCode.MEMBER_NOT_EXIST));
    
    		if(0 == tokenRepository.countByTokenValueAndMemberId(refreshToken, member.getMemberId())) {
                    	throw new ServiceException(ResultCode.REFRESH_TOKEN_EXPIRED);
                    }
    
                    TokenResDto tokenResDto = new TokenResDto();
                    JwtTokensVO jwtTokensVO = createToken(member.getUsername(), member.getRoles());
    
                    tokenResDto.setAccessToken(jwtTokensVO.getAccessToken());
                    tokenResDto.setRefreshToken(jwtTokensVO.getRefreshToken());
    
                    tokenRepository.deleteByMemberId(member.getMemberId());
    
                    Token token =new Token();
    
                    token.setTokenValue(jwtTokensVO.getRefreshToken());
                    token.setMemberId(member.getMemberId());
                    token.setExpiredDt(jwtTokensVO.getRefreshTokenExpirationDate());
    
                    tokenRepository.save(token);
    
    	        return tokenResDto;
           } else {
    		throw new ServiceException(ResultCode.REFRESH_TOKEN_EXPIRED);
           }
    }
    • ServiceException : ๊ณตํ†ต @ExceptionHandler Handler (์‚ฌ์šฉ์ž ์ •์˜)
    • memberRepository : ํšŒ์› Repository
    • tokenRepository : ํ† ํฐ Repository
    • BaseResDto : ์‚ฌ์šฉ์ž ์ •์˜ ๊ฐ์ฒด (resultCode, resultMessage)

    .orElseThrow(() -> new ServiceException(ResultCode.MEMBER_NOT_EXIST));

    Jpa Query Method์—์„œ Exception ๋ฐœ์ƒ์‹œ ์ปค์Šคํ…€ํ•œ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด Reponse ์ถœ๋ ฅ

    Spring Boot ์—์„œ ๊ณตํ†ต ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋ฐฉ๋ฒ•์ด ๊ถ๊ธˆํ•˜์‹ ๋ถ„์€ ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•ด์ฃผ์„ธ์š”.

     

    Spring Boot ๊ณตํ†ต Global Exception Handler

    ๐ŸŽˆ Spring์—์„œ ์ „์—ญ์ ์œผ๋กœ Exception์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํฌ์ŠคํŒ…ํ•œ๋‹ค. ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•˜๊ฒŒ ์žˆ๋‹ค. 1. ๋ฉ”์„œ๋“œ ๋‚ด ์˜ˆ์™ธ ์ƒํ™ฉ์„ ์˜ˆ์ธกํ•˜์—ฌ try-catch๋ฌธ ์‚ฌ์šฉ 2. ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€ํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ (validat

    developer-been.tistory.com




    ๐Ÿ’ก ์ง„ํ–‰ ๊ณผ์ •
    1๏ธโƒฃ validateToken() ํ•จ์ˆ˜ ํ˜ธ์ถœ
    2๏ธโƒฃ getUserPK() ํ•จ์ˆ˜๋กœ token claim subject (์—ฌ๊ธฐ์„œ๋Š” ํ•ธ๋“œํฐ๋ฒˆํ˜ธ) ๊ฐ’ ์–ป์€ ๋’ค, ํšŒ์› ์กฐํšŒ
    3๏ธโƒฃ createToken() ํ•จ์ˆ˜๋กœ accessToken, refreshToken ๊ฐฑ์‹ 
    4๏ธโƒฃ DB์—์„œ ๊ธฐ์กด refreshToekn ์‚ญ์ œ, ์ƒˆ๋กœ์šด refreshToken ์ถ”๊ฐ€
    5๏ธโƒฃ tokenResDto Return
    6๏ธโƒฃ ๋งŒ์•ฝ validateToken() ํ•จ์ˆ˜๋กœ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์„ ๊ฒฝ์šฐ refreshToken ๋งŒ๋ฃŒ Exception์„ ๋˜์ง‘๋‹ˆ๋‹ค.

     

     

    ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ์ด์–ด ๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

    https://developer-been.tistory.com/4

     

    Spring Security + JWT ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ (3)

    ๐Ÿ’ก ์ง€๋‚œ ํฌ์ŠคํŠธ์— ์ด์–ด์„œ Security์˜ 403 Forbidden ์—๋Ÿฌ๋ฅผ ํ•ธ๋“ค๋ง ํ•˜๋Š” Class๋ฅผ ์„ค์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Spring Security๋Š” AccessDeniedHandler์ธํ„ฐํŽ˜์ด์Šค์™€ AuthenticationEntryPoint์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ’ก AccessDenie

    developer-been.tistory.com

     

     

     

    Reference:

    https://to-dy.tistory.com/86

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€

Designed by Tistory.