본 포스팅은 스스로 공부한 내용을 정리하고 기록하기 위하여 올리는 내용이며, 잘못된 내용이 있을 수도 있음을 미리 밝힙니다. 잘못된 내용이 있거나, 더 좋은 방법이 있다면 댓글로 남겨주시기 바랍니다.
로그인을 구현하기에 앞서 어떤 방식으로 인증을 진행할건지에 대해서 결정해야 했습니다.
그러기 위해서 다음과 같은 개념들을 공부하였고, 결국엔 토큰으로 결정하였습니다.
세션이란 일정 시간 동안 같은 사용자(브라우저) 로부터 들어오는 일련의 요구를 하나의 상태로 보고, 그 상태를 유지시키는 기술입니다. 방문자가 웹 서버에 접속해 있는 상태를 하나의 단위로 보고 그것을 세션이라고 합니다. 특징은 다음과 같습니다.
쿠키는 사용자의 컴퓨터에 저장하는 작은 기록 정보 파일입니다. HTTP 에서 클라이언트의 상태 정보를 PC에 저장했다가 필요시 정보를 참조하거나 재사용합니다.
세션은 웹 서버에 클라이언트 상태를 유지하기 위해 정보를 저장해야 함으로 웹 서버에 부하를 걸수 있습니다. 쿠키는 보안에 취약할수 있습니다. 토큰은 이러한 세션의 단점과 쿠키의 단점을 해소화한 방식입니다.
토큰 방식중에는 JWT Token 이 있습니다.
JWT는 Json Web Token의 약자로 인증에 필요한 정보를 암호화시킨 토큰을 뜻하게 됩니다.
인증받은 사용자에게 토큰을 발급해주고, 서버에 요청을 할 때 HTTP 헤더에 토큰을 함께 보내어 인증받은 사용자(유효성 검사) 인지 확인합니다.
[ 인증 방식 ]
사용자가 로그인 시 올바른 사용자임을 확인하고, 클라이언트에게 Access Token(JWT)을 발급해준다.
클라이언트는 전달받은 토큰을 저장해 두고, 인증이 필요한 요청마다 토큰을 HTTP 헤더에 담아 보낸다.
서버에서는 암호화된 토큰을 복호화 해 올바른 요청인지 확인한다.
인증이 완료되고 서버는 요청에 응답한다
세션은 서버에서 상태를 유지해야함으로 서버에 부하를 일으킬수있습니다. 쿠키는 보안 문제가 발생할수있습니다. 반면에 토큰은 상태를 저장하지도 않으며, 보안 측면에서 봤을때 쿠키보다 뛰어납니다. 따라서 토큰을 사용하는 방식을 선택하였습니다.
라이브러리를 추가해 줍니다.
#build.gradle
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
implementation 'commons-io:commons-io:2.6'
Token 을 생성하기 위한 메소드를 작성합니다.
public static String createToken(String email,String role,String name, String key, Long expireTimeMs) {
Claims claims = Jwts.claims();
claims.put("email", email);
claims.put("role", role);
claims.put("name", name);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + expireTimeMs))
.signWith(SignatureAlgorithm.HS256, key)
.compact();
}
JWT 는 세 파트로 나누어집니다. 해더(header),페이로드(payload), 서명(signature)로 구성됩니다. JSON 형태인 각 부분은 BASE64로 인코딩 되어 표현됩니다.
Header: 이 코드에서는 헤더를 직접 설정하지 않았습니다.
Claims (Payload): JWT의 "클레임"은 토큰에 포함되는 정보를 나타내는 일련의 키-값 쌍입니다. 이 코드에서 Claims 객체는 토큰의 클레임 정보를 설정합니다. put 메서드를 사용하여 클레임 값을 추가합니다. 예를 들어, 이 코드에서는 "email", "role", "name"과 같은 클레임을 추가하고 해당 값을 설정합니다.
signWith : JWT를 서명합니다. SignatureAlgorithm.HS256는 HMAC-SHA256 알고리즘을 사용하여 서명을 생성합니다. 서명은 토큰의 무결성을 보장하며, 서명에 사용되는 키는 key 매개변수로 전달됩니다.
setIssuedAt : 토큰의 발급 일시를 설정합니다.
setExpiration : 토큰의 만료 시간을 설정합니다.
compact : JWT를 문자열로 변환하고 반환합니다. 이 문자열은 클라이언트에게 전달되며 JWT Token 이 됩니다.
Header + Payload + Signature를 인코딩하여 합치면 아래의 비밀스런 JWT 코드가 완성됩니다.
eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRlc3QzMjIzM2luZ0BuYXZlci5jb20iLCJyb2xlIjoiQ0xVQiIsIm5hbWUiOiLsobDsiJjtm4vrj5nslYTrpqwiLCJpYXQiOjE2OTc5ODc3MjgsImV4cCI6MTY5Nzk5MTMyOH0.U8YfscqZNzMq9wfPb3luHdLABvSHlOAIFRoiSVOeY3I
세션 및 쿠키 정리
https://dev-coco.tistory.com/161
https://dev-coco.tistory.com/61