
[ 임시 세션 생성 ]
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라 컨트롤러에 접근 불가능!

[ 토큰 헤더에 넣어주기 ]

여기다 토큰 넣어주면 이제 아무것도 안뜸
[ 토큰 만료 시 ]

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

오류 잡기
[ 토큰 틀려봄 ]

개발할 때에는 stackTrace 사용



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