{
"alg": "HS256",
"typ": "JWT"
}
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
implementation 'com.auth0:java-jwt:3.18.2'
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Member {
private int id;
private String username;
private String password;
}
@Data
public class LoginReq {
private String username;
private String password;
}
@Repository
public class TestRepository {
private final List<Member> members = new ArrayList<>();
private static int sequence = 0;
// 유저 생성
public TestRepository() {
members.add(new Member(++sequence, "kim", "1234"));
}
// 유저 확인
public boolean login(LoginReq req) {
return members.stream()
.anyMatch(m -> m.getUsername().equals(req.getUsername()) && m.getPassword().equals(req.getPassword()));
}
}
public class JwtUtils {
private JwtUtils() {}
// 토큰 생성
public static String generateToken(String username) {
// HS256 알고리즘
Algorithm algorithm = Algorithm.HMAC256("secret");
return JWT.create()
.withIssuer("k")
.withIssuedAt(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()))
.withExpiresAt(Date.from(LocalDateTime.now().plusDays(1L).atZone(ZoneId.systemDefault()).toInstant()))
.withClaim("username", username)
.sign(algorithm);
}
// 토큰 검증
public static boolean verifyToken(String token) {
Algorithm algorithm = Algorithm.HMAC256("secret");
try {
DecodedJWT verify = JWT.require(algorithm)
.build().verify(token);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// 토큰 검증 제외 요청 URI 리스트
String[] excludeUri = {
"/login"
};
String requestURI = httpServletRequest.getRequestURI();
if (Arrays.asList(excludeUri).contains(requestURI)) {
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
try {
// 헤더에서 Authorization 값을 가져와 검증
String authorization = httpServletRequest.getHeader("Authorization");
String token = authorization.replace("Bearer ", "");
if (JwtUtils.verifyToken(token)) {
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
httpServletResponse.getWriter().println("Unauthorized");
}
} catch (Exception e) {
httpServletResponse.getWriter().println("Unauthorized");
}
}
}
}
필터 등록
@ServletComponentScan(basePackages = {"com.example.jwt.filter"}) public class JwtApplication { ... }
@RestController
@RequiredArgsConstructor
public class TestController {
private final TestRepository testRepository;
@PostMapping("/login")
public ResponseEntity<?> login(LoginReq loginReq) {
return testRepository.login(loginReq) ?
ResponseEntity.status(HttpStatus.OK).header("token", JwtUtils.generateToken(loginReq.getUsername())).body("success") :
ResponseEntity.status(HttpStatus.BAD_REQUEST).body("fail");
}
@GetMapping("/hello")
public String hello() {
return "hello";
}
}