본문 바로가기

Java

API Security & JWT

반응형

- 웹 서비스 인증 방식 중 하나인 토큰을 통한 인증방식 이해

- JWT라는 표준 JSON Web Token 구현

 

어플리케이션에서 보안은 주로 인증(Authentication) 과 인가(Authorization)을 의미하며 Spring Security에서 다루어집니다. 

id/pw 기반의 인증방식은 최근 더욱 강력한 인증방식인 2단계 인증, 지문, 안면인식을 포함한 하드웨어 인증 방식 등 여러 강력한 인증방식으로 보완/대체 되고 있습니다.

 

인증과 인가

인증: 클라이언트가 자신이 주장하는 사용자와 같은 사용자인지를 확인하는 과정

인가: 권한부여, 클라이언트가 하고자하는 작업이 해당 클라이언트에게 허가된 작업인지 확인하는 과정

 

 

Spring Security

- Spring에서 보안을 위한 별도의 모듈입니다.

- 강력한 인증과 권한 관련 framework입니다. 

- 요청에 대한 출입 허가증/ 인증한 사용자에게 어느정도까지 허용할 것인가에 대해 정의

- REST API에 대한 권한도 spring security가 사용 중

 

JWT

- 보안에 최근에 많이 사용되고 있습니다.

- JWT 토큰 형태로 많이 사용됩니다.

 

 

주요 인증 방식

  • 로그인 기반 인증(크레덴셜 기반 인증) : 토큰 기반
  • 인증정보를 다른 어플리케이션으로 전달 : 제3자가 인증을 처리하는 방식, OAuth 2, facebook/google 같은 소셜 계정들 이용
  • 2단계 인증: 핸드폰, 이메일 등을 통한 2번의 인증방법
  • 하드웨어 인증

 

서버 기반 인증 시스템의 문제점

세션기반의 인증은 사용자가 로그인을 했을 때, 서버 메모리에 이 user에 대한 정보를 저장해둡니다.

웹 어플리케이션 서버 instance가 하나만 있는 것이 아니라 이중화, clustering되어 있습니다.

요청이 오면 load balancer를 통해 각각의 server로 가게 되고 어느 서버로 유입될지 모르기 때문에 각 session정보를 서버마다 공유를 해야합니다. 

이 방식은 서버가 확장될수록 (클라우드에서 auto scaling) session정보가 같이 복제 되어야 서비스를 끊김없이 사용가능합니다. 

CORS(Cross-Origin Resource Sharing): 세션기반 로그인 유지시 쿠키를 사용하게 되는데 쿠키를 여러 도메인에서 관리하는 것에대한 번거로움도 발생합니다.

 

 

토큰 기반 인증 시스템 작동 원리

유저가 아이디, 패스워드 통해 로그인 수행합니다. 서버측에서 해당 정보 확인 후 인증에대한 토큰을 생성합니다. 

서버는 session이 아닌 외부장치에서 client에 대한 정보를 저장해둡니다.

string 형태의 token을 client측에서 저장을 해둡니다. 

그 다음 부터는 요청 시 token 정보를 request header에 넣어서 요청을 해줍니다.

서버에서는 token을 보고 client 식별 및 응답을 생성합니다.

token은 네트워크상에서 해커가 볼 수 있긴 하지만 양쪽 키를 통해 잠기기 때문에 위조하기 어렵습니다.

또한, token 자체에 만료 기간을 정해두기 때문에 효율적으로 token 활용이 가능합니다.

쿠키를 사용하지 않기 때문에 보안성도 강화됩니다.

 

토큰 기반 인증 시스템의 장점

1. 무상태(stateless) 이며, 확장성(scalability)이 있음

2. 보안성

- 쿠키 사용이 없다

- 취약점은 존재. 네트워크 상 탈취 가능.

- String으로 이뤄진 데이터

3. extensibility

- 토큰에 여러 데이터 담을 수 있음

- body 부분에 여러 데이터 담을 수 있음

- 기능 확장 가능

4. 여러 플랫폼 및 도메인

-  CORS: 아무 도메인에서나 토큰만 유효하면 요청이 정상 처리

5. 웹 표준 기반

- JWT

- 토큰의 format을 공식 표준으로 정해줌

 

JWT(JSON Web Token)

- String을 사용하기 때문에 웹에 가장 적합

- 웹 표준으로 다양한 프로그래밍 언어에서 지원

- 자체적으로 정보를 다 포함하고 있기 때문에 훨씬 더 효율적으로 사용 가능

- HTTP header, parameter로 전달 가능

- JWT 사용 상황: 회원 인증, 정보 교환 등

 

JWT 구조

     aaaaaa    .     bbbbbb      . cccccc

헤더(header)  . 내용(payload)  . 서명(signature)

 

1) 헤더 - 두가지 정보

- typ : 토큰의 타입을 지정

- alg : 해싱 알고리즘 지정(HMAC SHA256, RSA ... )

{

    "typ" : "JWT",

    "alg" : "HS256"

}   

 

2) 내용

- 토큰에 담을 정보인 클레임이 포함됨 (name, value 쌍으로 구성)

- 클레임(claim)은 다음 세 분류로 나뉨

  • 등록된 클레임(registerd) - iss, sub, aud, exp, nbf, sat, jti
  • 공개 클레임(public) - 충돌 방지 이름 필요(주로 URI 형식으로 네이밍)
  • 비공개 클레임(private) - 클라이언트와 서버 간의 협의 하에 사용되는 클레임 이름들

{

    "iss" : "example.com",

    "exp" : "12312312312",

    "https://example.com/jwt_claims/is_admin": true,

    "userId" : "1231231",

    "userName": "hi"

}

3) 서명

- 헤더의 인코딩 값과 정보의 인코딩 값을 합친후 주어진 비밀키로 해쉬하여 생성

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

위 사이트에서 별도로 jwt 로 인코딩, 디코딩하는 부분이 표기되어 있습니다.

 

서버에서는 토큰을 발행하고 parsing 하는 역할을 합니다.

 

 

구현하기

dependency 추가

JWT 사용을 위해서 dependency를 아래와 같이 pom.xml에 추가해줍니다.

pom.xml

 

 

토큰을 생성하고 토큰을 가진 사용자를 확인하는 메소드를 구현합니다.

service
controller

 

 

Controller까지 정의하면 구현 완료입니다~

 

반응형

'Java' 카테고리의 다른 글

HashMap & HashSet  (0) 2020.09.16
Content-Type  (0) 2020.07.14
Rest 아키텍처  (0) 2020.03.04
JUnit Test  (0) 2020.01.05
Spring Security  (0) 2019.12.30