Spring 프로젝트 시작하기 - 보안 ) Jwt Token 쿠키 발급

데이터를 다루는 API를 누구나 어디에서나 자유롭게 호출해서 쓸수 있다면 보안적으로 큰 문제가 되시겠다.

 

이를 막을수 있는방법은 여러가지가 있는데 클라이언트의 서버를 제한하거나( CORS 정책 ), 진입 사용자를 판별( 세션, 쿠키 ) 하는 방법등이 있다.

 

이글에서 다루어볼 방법은 Jwt Token으로 암호화된 유저정보를 쿠키에 저장해서 API 진입시마다 확인하는 방법이다.

 

준비과정

1. 유저 정보로 판별하려면 이미 유저데이터를 가지고있어야 한다. 고로 DB연결 및 유저정보는 테이블에 이미 들어있어야한다.

참고 : https://debugggggger.tistory.com/30

 

Spring 프로젝트 시작하기 - DB 연결(JPA)

프로젝트에 JPA로 Mysql DB를 연결해볼것이다.1. build.gradle 파일에서 의존성을 추가한다.dependencies { ... // JPA implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // mysql implementation group: 'mysql', name: '

debugggggger.tistory.com

 

2. Jwt Token 생성에 필요한 라이브러리 추가

dependencies {
	...
	// JwtToken
	implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'
	implementation 'javax.xml.bind:jaxb-api:2.3.0'
    ...
}

 

3. Jwt Token에서 사용할 데이터 DTO를 생성한다.

중요한 정보는 포함하면 안되며, 유저를 판별할 수 있는 최소의 값들로 넣어야 한다.

지금은 uId (user ID), uIdx (user index), cIdx (customer idx) 을 넣으려고 한다.

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class JwtTokenDto {
    long cIdx;
    long uIdx;
    String uId;
}

 

4. 토큰 생성에 필요한 값들을 프로퍼티에 넣는다. (application-머시기.yml)

jwt:
  access:
    name: AccessToken // 저장할 Cookie의 키값
    secret-key: 7d83b6e5f7c918f90ba054de9e274a6d04fc6c5fcfa57ebfc6fcd196e4e85b4c // 암호화 키값
    expiration-time: 2592000 // 만료시간. 1000(ms) * 60(분) * 60(시) * 24(하루) * 30(일) = 한달

 

 

그럼 토큰을 발급하려면 언제 발급을 해주어야할까?

바로 로그인 되시겠다.

 

Controller

@Slf4j
@RequestMapping("/auth")
@RestController
@RequiredArgsConstructor
public class AuthController {

    private final JwtProvider jwtProvider;
    private final AuthService authService;

    /**
     * 로그인
     *
     * @return 멤버 리스트
     * GET /auth/login
     */
    @PostMapping("/login")
    public ResponseEntity<ServerResponse> login(HttpServletRequest request, @RequestBody AuthLoginRequest param, HttpServletResponse response) {
        log.debug("[{}] Controller 진입", Thread.currentThread().getStackTrace()[1].getClassName());
        JwtTokenDto user = authService.login(request, param);

        // 로그인 토큰 생성
        jwtProvider.createAccessTokenString(user, response);

        return ResponseEntity.ok(ServerResponse.SUCCESS);
    }
}

로그인 로직을 위한 Controller를 만들었다.

로그인 서비스로직은 추후에 자세히 다루어보겠다.

우선은 Token 생성에 필요한 정보들만 리턴하도록 만들었다.

 

AuthLoginRequest는 로그인할때 받는 ID, PW등을 규정하면 된다.

 

이제 실제 토큰을 생성하는 JwtProvider를 살펴보자.

 

JwtProvider

@Slf4j
@Component
@RequiredArgsConstructor
public class JwtProvider {
    @Value("${jwt.access.name}")
    private String TOKEN_COOKIENAME;

    @Value("${jwt.access.secret-key}")
    private String accessTokenSecret;

    @Value("${jwt.access.expiration-time}")
    private long accessExpirationTime;

    /**
     * response에 jwt access token을 포함한 Cookie를 추가한다.
     *
     * @param user
     * @return
     */
    public void createAccessTokenString(JwtTokenDto user, HttpServletResponse response) {
        String token = Jwts.builder()
                .setHeaderParam("type", "JWT") // JWT를 사용할것이다.
                .claim("cIdx",user.getCIdx()) // claim으로 데이터들 입력
                .claim("uId", user.getUId())
                .claim("uIdx", user.getUIdx())
                .setIssuedAt(new Date(System.currentTimeMillis())) // 생성시간 (현재시간)
                .setExpiration(new Date(System.currentTimeMillis() + accessExpirationTime)) // 만료시간
                .signWith(SignatureAlgorithm.HS256, accessTokenSecret.getBytes(StandardCharsets.UTF_8)) // 암호화 설정
                .compact();
        log.info("createAccessToken:{}", token);
        // 토큰쿠키 생성
        Cookie accessTokenCookie = new Cookie(TOKEN_COOKIENAME, token);
        accessTokenCookie.setPath("/");
        accessTokenCookie.setMaxAge((int) accessExpirationTime);
        response.addCookie(accessTokenCookie);
    }
}

윗부분에서는 프로퍼티에 저장했던 값들을 가져온다.

createAccessTokenString에서는 JwtToken String을 생성해서 token에 저장하고,

Cookie에 TOKEN_COOKIENAME (프로퍼티에 저장된 값으로는 " AccessToken ") 라는 이름으로 토큰을 넣어준다.

 

 

이런 과정을 거치면 API 리턴을 받은 클라이언트에서 Token 쿠키를 저장하게 된다.

 

테스트

Body에 적절한 body값(ID, PW)을 입력하고 Send해서 OK를 리턴받은 후, Cookie를 확인해보자.

(사실 바로는 확인이 안되고 API 탭을 뒤적거려야 새로고침된다.)

이렇게 AccessToken이라는 이름으로 토큰이 저장된것을 확인할 수 있다.

 

토큰 확인

https://jwt.io/

위 사이트에 들어가면 토큰의 값을 확인할 수 있다.

 

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

?? 암호화했는데 데이터를 왜 막 볼수있음?? >> 에 대한 포스팅을 써보았다 : https://debugggggger.tistory.com/43

 

그러므로 토큰에 사용자의 중요정보를 넣지 않도록 조심하는것이 좋겠다.