웹인증.2(JWT Token)

ys·2024년 3월 1일
  • JWT(Json Web Token) 은 웹 표준으로써
  1. 데이터를 Json 객체를 사용하여
  2. 가볍고 자가 수용적인 방식으로
  3. 정보를 안전하게 전달할 수 있도록 설계된
  4. 토큰 기반의 인증 방식이다
  • JWT는 URL,Http Header, HTML Form 과 같은 다양한 방식으로 전달될 수 있다
  • 서버와 클라이언트간의 인증 정보를 포함한다

JWT 구성

  • JWT는 Header, Payload, Signature 이렇게 3부분으로 구성된다

  • Header는 JWT 타입, 암호화 알고리즘등을 포함하고, Json형태이다

  • Payload는 클레임 정보와, 암호화 알고리즘등을 포함하고 ,Json 형태이다

    • 클레임 정보는 사용자 Id,권한 같은게 들어가고 커스텀 가능하다
    • 암호화 알고리즘을 통해 읽을 수 있으므로, 중요한 정보는 넣지 않는다
  • Signiture는 Header와 Payload를 조합해, 비밀키를 이용해, 생성된 서명값이다

    • 서명 값은(해쉬 알고리즘 이용) 토큰의 무결성을 보장하며
    • JWT를 조작하지 않았다는 것을 검증한다
  • Payload 부분은 누구든지 값을 꺼내, Base64URLEncode를 통해 값이 무엇인지 확인할 수 잇다

  • 중요한 정보보단, 참고할만한 정보를 담아두는 영역으로 생각하자
    -JWT 토큰은 해시-알고리즘을 통해서 서명(signiture)을하게 되는데

  • Vreify Sihniture

  • 다음 부분을 가지고 시크릿 키와 해시 알고리즘을 통해 암호화한 후, 마지막줄에 붙여준다!

hash 알고리즘 : A라는 값에 어떠한 키를 넣고 암호화하면 항상, 같은 값이 나온다

  • 빨간 부분의 값을 통해 해시 알고리즘을 돌려, 뒤쪽의 값과 동일한지를 검증한다
  • 만약, 동알하지않으면 Verify Signiture값은 변형되었다고 본다
  • 변형되었다는 것은 누군가 토큰의 값을 건드렸다라는 의미이다
  • 만약 동일하다면, 이 토큰은 유효하다!라고 할 수 있다

JWT 인증 과정

  1. 클라이언트가 서버에 로그인 정보(id,password)를 보낸다
  2. 서버는 로그인 요청을 검증하고 -> 유효하다면 JWT를 생성하여 클라이언트에게 반환(쿠키나, json바디에 담아 request body로 보낸다)
  3. 클라이언트는 이후 요청에 JWT를 포함시켜서 전송
  4. 서버는 시크릿 키를 가지고 JWT를 검증하여 클라이언트의 인증 여부를 확인한다

dependency

  • jwt를 일일이 구현하기는 어렵고 복잡하다
  • jwt에서 제공하는 라이브러리를 이용하자!
	// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api
	implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
	// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl
	runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
	// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson
	runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'

code

  • token을 만들어주는 create()메서드 : token-type : String
  • token을 검증해주는 validation()메서드

test 코드

@SpringBootTest
class JwtApplicationTests {
	@Autowired
	private JwtService jwtService;
	
	@Test
	void tokenCreate(){
		HashMap<String, Object> claims = new HashMap<>();
		claims.put("user_id",923);

		LocalDateTime expiredAt = LocalDateTime.now().plusMinutes(10);

		String jwtToken = jwtService.create(claims, expiredAt);
		System.out.println("jwtToken = " + jwtToken);

	}
	@Test
	void  tokenCreated(){
		String token = "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo5MjMsImV4cCI6MTcwOTEyMTIzN30.7a25t16zha9Vhxvw5Weq9QnfkDeHWEGe6EsLyefakQE";

		jwtService.validation(token);
	}

}
  • 실제 검증 부분은, 저 token값을 클라이언트가 http message에 넣어서 서버에 보내준다
  • 지금은 간단한 test 코드이기 때문에, 검증 토큰을 복사해서 string으로 적어두었다

JWT Token 장단점

장점

  1. 토큰 기반의 인증 방식이므로, 서버 측에서 별도의 세션 저장소를 유지할 필요 없다
  • redis 같은, session clustring을 통해 서비스를 할 필요가 없다(서버 유지 보수에 편리하다)
  1. json 형식으로 인코딩 -> 플랫폼간 전송 및 구현 쉽다
  2. Signatrue을 사용해 무결성을 보장, 토큰 변조 여부 쉽게 검증 가능

단점

  1. JWT 크기가 커지면, 네트워크 광역폭이 증가(크게 영향 X)
  2. JWT 한번 발급 후에, 내부 정보 수정 불가 -> 만료시간 짧게해서 해결
  3. JWT를 탈취당하면, 해당 토큰을 사용해 모든 요청이 인증됨... 보안 위협이 될수 있다. https같은 보안 프로토컬을 사용해 JWT를 서버에 전송하자!
  • 물론 3번은 모든 모든 인증에 비슷하다!!!
profile
개발 공부,정리

0개의 댓글