stateless 세션으로 만들자! (코드)

coding S's avatar
Apr 19, 2024
stateless 세션으로 만들자! (코드)

[ 임시 세션 생성 ]

package shop.mtcoding.blog.user; import lombok.Builder; import lombok.Data; import java.sql.Timestamp; @Data public class SessionUser { private Integer id; private String username; private String email; private Timestamp createdAt; @Builder public SessionUser(Integer id, String username, String email, Timestamp createdAt) { this.id = id; this.username = username; this.email = email; this.createdAt = createdAt; } public SessionUser(User user) { this.id = user.getId(); this.username = user.getUsername(); this.email = user.getEmail(); this.createdAt = user.getCreatedAt(); } }
package shop.mtcoding.blog._core.utils; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import shop.mtcoding.blog.user.SessionUser; import shop.mtcoding.blog.user.User; import java.util.Date; public class JwtUtil { //목적 : 토큰 생성 public static String create(User user) { String jwt = JWT.create() .withSubject("blog") .withExpiresAt(new Date(System.currentTimeMillis()+ 1000L * 60L * 60L)) //토큰 생성되고 1시간 .withClaim("id", user.getId()) .withClaim("username", user.getUsername()) .sign(Algorithm.HMAC512("metacoding")); //내가 생성하고 내가 검증하니까 RSA 필요 없음. 검증을 다른 서버가 하면 RSA쓰자. 지금은 대칭키 씀 //metacoding은 나중에 환경변수로 변경해야한다. aws했던 그 환경변수 말하는 듯 return jwt; } //목적 : 검증 public static SessionUser verify(String jwt) { DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC512("metacoding")).build().verify(jwt); int id = decodedJWT.getClaim("id").asInt(); String username = decodedJWT.getClaim("username").asString(); return SessionUser.builder() .id(id) .username(username) .build(); } }
JWT를 이용하여 사용자 인증 정보를 검증한 후, 검증된 정보를 바탕으로 SessionUser 객체를 생성하여 이를 세션에 저장하고 이용하는 방식 매 요청마다 JWT를 검증하고, 검증된 사용자 정보를 임시 세션에 저장하여 사용합 응답할 때 까지만 세션을 사용하는 것. 임시 세션 ...
 

[ LoginInterceptor ]

package shop.mtcoding.blog._core.interceptor; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import shop.mtcoding.blog._core.errors.exception.Exception401; import shop.mtcoding.blog._core.utils.JwtUtil; import shop.mtcoding.blog.user.SessionUser; import shop.mtcoding.blog.user.User; // /api/** 인증 필요 주소 public class LoginInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // Bearer jwt 토큰이 들어옴 String jwt = request.getHeader("Authorization"); if (jwt == null) { throw new Exception401("jwt 토큰을 전달해주세요"); } jwt = jwt.replace("Bearer ", ""); //검증 try { SessionUser sessionUser = JwtUtil.verify(jwt); // 임시 세션 (jsessionId는 필요 없음) HttpSession session = request.getSession(); session.setAttribute("sessionUser", sessionUser); return true; } catch (Exception e) { return false; } } }
💡
토큰을 안 들고 오면 return false라 컨트롤러에 접근 불가능!
notion image

[ 토큰 헤더에 넣어주기 ]

notion image
💡
여기다 토큰 넣어주면 이제 아무것도 안뜸
 

[ 토큰 만료 시 ]

notion image
💡
어떤 오류를 날려야하는지 (401이니 403이니) 알기 위해 stackTrace를 적어줌 TokenExpiredException 뜸
notion image
💡
오류 잡기
 

[ 토큰 틀려봄 ]

notion image
💡
개발할 때에는 stackTrace 사용
notion image
notion image
notion image

 
package shop.mtcoding.blog._core.interceptor; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.exceptions.TokenExpiredException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import shop.mtcoding.blog._core.errors.exception.Exception401; import shop.mtcoding.blog._core.errors.exception.Exception500; import shop.mtcoding.blog._core.utils.JwtUtil; import shop.mtcoding.blog.user.SessionUser; import shop.mtcoding.blog.user.User; // /api/** 인증 필요 주소 public class LoginInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // Bearer jwt토큰 String jwt = request.getHeader("Authorization"); if(jwt == null){ throw new Exception401("jwt 토큰을 전달해주세요"); } jwt = jwt.replace("Bearer ", ""); // 검증 try { SessionUser sessionUser = JwtUtil.verify(jwt); // 임시 세션 (jsessionId는 필요 없음) HttpSession session = request.getSession(); session.setAttribute("sessionUser", sessionUser); return true; }catch (TokenExpiredException e){ throw new Exception401("토큰 만료시간이 지났어요. 다시 로그인하세요"); }catch (JWTDecodeException e){ throw new Exception401("토큰이 유효하지 않습니다"); }catch (Exception e){ throw new Exception500(e.getMessage()); } } }
하여튼 이렇게 주면 이후는 프런트가 알아서 할 것
 
Share article

codingb