# 위에서 도커 허브 node 이미지를 기반으로 로컬로 다운로드 및 캐싱 되었기 때문에 이미지를 가져올 수 있다.
FROM node:18.4.0
# 만약 컨테이너 안의 이미지의 경로가 /app 이런식으로 되어있다면 작업할 div 경로를 설정할 수도 있다.
# 설정해주면 COPY 의 두번째 경로를 ./ 이것으로 했을 때 자동으로 /app 경로가 된다.
WORKDIR /app
# package.json 파일을 복사한다. 만약 다시 빌드할 때 변경사항이 없을 경우 npm install까지 그냥 넘어간다.
COPY package.json /app
# 이미지를 받으면 npm install을 자동으로 해줌
RUN npm install
# 어떤 파일이 이미지에 들어가야 하는지
# 첫 번째 .은 이 프로젝트의 모든 폴더 및 파일들 (Dockerfile을 제외한)
# 두 번째 .은 파일을 저장할 컨테이너 내부 경로 (ex /app)
COPY . /app
# 배포환경으로 설정
ENV NODE_ENV=production
RUN npm run build
# 도케에게 우리가 서버를 실행할 포트를 말해준다.
EXPOSE 3000
# 이미지가 생성될 때 실행되지 않고 컨테이너가 실행될 때 수행하는 명령어
CMD ["npm","start"]
package web.backend.auth;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
import java.util.function.Function;
@Component
public class JwtTokenManager {
private static final String secret = "secretKey!!!";
// 토큰 유효 기간
public static final long JWT_TOKEN_VALIDITY = 60 * 60 * 24 * 1000L; //하루
/**
* 토큰 생성
*/
public String generateToken(String id, Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims) // 정보 저장
.setId(id)
.setIssuedAt(new Date(System.currentTimeMillis())) // 토큰 발행 시간 정보
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY)) // set Expire Time
.signWith(SignatureAlgorithm.HS512, secret)// 사용할 암호화 알고리즘과
// signature 에 들어갈 secret값 세팅
.compact();
}
/**
* 토큰 id 반환
*/
public String getTokenIdFromToken(String token) {
return getClaimFromToken(token, Claims::getId);
}
/**
* 토큰이 만료되었는지 Boolean 반환
*/
public Boolean isTokenExpired(String token) {
final Date expiration = getClaimFromToken(token, Claims::getExpiration);
return expiration.before(new Date());
}
/**
* 토큰 자체에 대한 정보 추출(id, expire 등)
*/
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token).getBody();// JWT payload 에 저장되는 정보단위
return claimsResolver.apply(claims);
}
/**
* 토큰 안의 모든 정보 추출
*/
public Claims getClaimsFromToken(String token) {
final Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token).getBody();// JWT payload 에 저장되는 정보단위
return claims;
}
}
3. Test
test/java/web/backend/auth/JwtTest
package web.backend.auth;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
@Slf4j
public class JwtTest {
@Autowired
JwtTokenManager jwtTokenProvider = new JwtTokenManager();
Map<String, Object> map = new HashMap<>();
@BeforeEach
public void before() {
map.put("userId","teepo");
}
@Test
public void test() {
// 토큰 생성
String tokenString = jwtTokenProvider.generateToken("1", map);
log.info("tokenString={}",tokenString);
assertNotNull(tokenString);
// 토큰 Id
String tokenId = jwtTokenProvider.getTokenIdFromToken(tokenString);
log.info("tokenId={}", tokenId);
assertEquals("1",tokenId);
// 토큰이 만료되었는지
Boolean tokenExpired = jwtTokenProvider.isTokenExpired(tokenString);
log.info("tokenExpired={}",tokenExpired);
assertEquals(false, tokenExpired);
// 토큰 안의 모든 정보
Claims tokenClaims = jwtTokenProvider.getClaimsFromToken(tokenString);
log.info("tokenClaims={}", tokenClaims);
// before 메소드에서 생성한 데이터 조회
String value = tokenClaims.get("userId").toString();
log.info("userId={}",value);
assertEquals("teepo", value);
}
}
4. 로그 확인
이번엔 클라이언트한테 요청을 받고, 쿠키 안에 Token을 넣은 뒤 확인해보자. 코드는 전 포스트에서 이어진다.
1. Controller
backend/module/user/UserController
@PostMapping("/test")
public CommonResponse<String> jwtGenerateTest(HttpServletResponse response, @RequestBody User user) {
return new CommonResponse<String>(true, userService.jwtTest(response,user));
}
2. Service
backend/module/user/UserService
JwtTokenManager jwtTokenManager = new JwtTokenManager();
public String jwtTest(HttpServletResponse response ,User user) {
Map<String, Object> tokenMap = new HashMap<>();
tokenMap.put("userId", user.getUserId());
String tokenString = jwtTokenManager.generateToken("token1", tokenMap);
log.info("tokenValue={}",jwtTokenManager.getClaimsFromToken(tokenString));
Cookie cookie = new Cookie("token1",tokenString);
cookie.setMaxAge(86400000); // 하루
response.addCookie(cookie);
return "ok";
}
$ docker pull redis # redis 이미지 받기
$ docker images # redis 이미지 확인
$ docker run -p 6379:6379 --name some-redis -d redis # redis 시작하기
$ docker ps # redis 실행 확인