본문 바로가기

공부/Spring

스프링 부트 3 백엔드 개발자 되기_17

회원가입되고  db에 데이터 들어간거까지 체크했는데 로그인이 안됨=>
 
@Override
    public boolean isAccountNonLocked() {
        return true;
    }


여기 true를 false라고 해놔서 안된거였음


9장
JWT로 로그인/로그아웃 구현하기
학습목표 : 토큰 기반 인증과 JWT,리프레시 토큰의 개념을 이해하고 토큰 기반 인증인 JWT 토큰 서비스를 구현하고 적용합니다


사용자가 서버에 접근할 때 이 사용자가 인증된 사용자인지 확인하는 방법은 다양함
대표적인 사용자 인증 확인 방법에는 서버 기반 인증과 토큰 기반 인증이 있다.

세션 기반 인증?
스프링 시큐리티에서는 기본적으로 세션 인증을 제공
8장같은 경우 스프링 시큐리티에서 기본적으로 제공해주는 세션 기반 인증을 사용해 사용자마다 사용자의 정보를 담은 세션을 생성하고 저장해서 인증을 함 => 이를 세션 기반 인증이라 한다
토큰 기반 인증?
토큰은 서버에서 클라이언트를 구분하기 위한 유일한 값,서버가 토큰을 생성해서 클라이언트에게 제공하면 클라이언트는 이토큰을 갖고 있다가 여러 요청을 이 토큰과 함꼐 신청
그럼 서버는 토큰만 보고 유효한 사용자인지 검증

토큰을 전달하고 인증받는 과정
토큰은 요청과 응답에 함께 보냄, 

1.클라이언트가 로그인 요청 (클라이언트가 아이디와 비밀번호를 서버에 전달하면서 인증을 요청)
2.서버가 토큰 생성 후 응답(서버는 아이디와 비밀번호를 확인해 유효한 사용자인지 검증, 유효한 사용자일 경우 토큰 생성해서 응답)
3.클라이언트가 토큰 저장(서버에서 준 토큰 저장)
4.클라이언트가 토큰 정보와 함께 요청(인증이 필요한 api를 사용할 때 토큰을 함께 보냄)
5.서버가 토큰 검증(서버가 토큰이 유효한지 검증)
6.서버가 클라이언트에 응답(토큰이 유효하면 클라이언트가 요청한 내용을 처리)


토큰 기반 인증 특징
1.무사태성 2.확장성 3.무결성


1.무상태성
사용자의 인증 정보가 담겨 있는 토큰이 서버가 아닌 클라이언트에 있어서 서버에 저장할 필요가 없음
서버가 데이터를 유지하려고 있으려면 그만큼 자원을 소비해야 함
그런데 토큰 기반 인증에서는 클라이언트에서 인증 정보가 담긴 토큰을 생성하고 인증 => 클라이언트에서는 사용자의 인증 상태를 유지하면서 이후 요청을 처리해야하는데 이것을 상태를 관리한다고 함
이렇게하면 서버 입장에서는 클라이언트의 인증 정보를 저장하거나 유지하지 않아도 되어 완전한 무상태로 효율적인 검증 가능

2.확장성
무상태성은 확장성에 영향을 줌
서버 확장할 때 상태 관리를 신경쓸 필요가 없어서 서버 확장에도 용이
ex) 결제 서버와 주문 서버가 분리되어 있는 환경
세션 인증 기반일 경우 각각 api에서 인증을 해야하는데
토큰 기반 인증에서는 토큰을 가지는 주체가 서버가 아닌 클라이언트
그래서 이미 가지고 있는 하나의 토큰으로 결제 서버와 주문 서버에게 요청을 보낼 수 있다
또한 페이스북 로그인, 구글 로그인 같이 토큰 기반 인증을 사용하는 다른 시스템에 접근해 로그인 방식 확장하거나 이를 활용해 다른 서비스에 권한을 공유할 수 있다

3.무결성
토큰 방식은 HMAC기법이라고도 부름, 토큰을 발급한 이후에는 토큰 정보를 변경하는 행위는 할 수 없다 => 토큰의 무결성이 보장됨
만약 누군가 토큰을 한글자라도 변경하면 서버에서는 유효하지 않은 토큰이라고 판단



#JWT
발급받은 JWT를 이용해 인증 하려면 HTTP 요청 헤더 중에 Authorization 키값에 Bearer+ JWT 토큰값을 넣어 보내야함

JWT의 구조
.을 기준으로 헤더,내용,서명으로 이루어져 있음
ex) aaaaa.bbbbbb.cccccc

헤더 : 
헤더에는 토큰 타입과 해싱 알고리즘을 지정하는 정보를 담음

다음의 경우 JWT토큰, HS256 해싱 알고리즘을 사용한다는 내용

##토큰 타입과 해싱 알고리즘 지정 예##
{
"typ": "JWT",
"alg": "HS256"
}

내용 :
내용에는 토큰과 관련된 정보를 담습니다.
내용의 한 덩어리를 클레임이라고 부르며 클레임은 키값의 한 쌍으로 이루어져 있음
클레임은 등록된 클레임, 공개 클레임, 비공개 클레임으로 나눌 수 있다


등록된 클레임은 토큰에 대한 정보를 담는 데 사용함


공개 클레임은 공개되어도 상관없는 클레임을 의미 
충돌을 방지할 수 있는 이름을 가져야하며 보통 클레임 이름을 URI로 짓는다
비공개 클레임은 공개되면 안되는 클레임을 말함 : 클라이언트와 서버 간의 통신에 사용


서명 :
서명은 해당 토큰이 조작됐거나 변경되지 않았음을 확인하는 용도로 사용
헤더의 인코딩 값과 내용의 인코딩 값을 합친 후 주어진 비밀키를 사용해 해시값을 생성

토큰 유효기간:
만약 토큰을 주고 받는 환경이 보안에 취약해서 토큰 자체가 노출된다면? 
토큰은 이미 발급되면 그 자체로 인증 수단이되어 서버는 토큰과 함께 들어온 요청이 토큰을 탈취한 사람의 요청인지 확인할 수 없다


리프레시 토큰이 있다면?
토큰의 유효기간이 짧으면 위 상황 방지 가능? => 사용자 입장에서 불편 
이러한 불편한점을 해결하기 위해 리프레시 토큰이 등장
리프레시 토큰은 액세스 토큰과 별개의 토큰
사용자를 인증하기 위한 용도가 아닌 액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급하기 위해 사용
액세스 토큰의 유효기간은 짧게 설정, 리프레시 토큰의 유효기간은 길게 설정하면 공격자가 액세스 토큰을 탈취해도 몇 분 뒤에는 사용할 수 없는 토큰이 되어 안전


리프레시 토큰 과정
1.클라이언트가 서버에 인증 요청
2.서버는 클라이언트에서 전달한 정보를 바탕으로 인증 정보가 유효한지 확인한 뒤 액세스 토큰과 리프레시 토큰을 만들어 클라이언트에게 전달+ 클라이언트는 토큰을 저장
3.서버에서 생성한 리프레시 토큰은 DB에도 저장
4.인증을 필요로하는 api를 호출할 때 클라이언트에서 저장된 액세스 토큰과 함께 api를 요청
5.서버에서 전달받은 액세스 토큰이 유효한지 검사한 뒤 유효하다면 클라이언트에서 요청한 내용을 처리
6.시간이 지나고 액세스 토큰이 만료된 뒤 클라이언트에서 원하는 정보를 얻기 위해 서버에게 api 요청을 보냄
7.서버에서 액세스 토큰이 유효한지 검사
8.클라이언트에서는 이 응답을 받고 저장해둔 리프레시 토큰과 함께 새로운 액세스 토큰을 발급하는 요청을 전송
9.서버에서는 전달받은 리프레시 토큰이 유효한지 DB에서 리프레시 토큰을 조회한 후 저장해둔 리프레시 토큰과 같은지 확인 
10.만약 유효한 리프레시 토큰이라면 새로운 액세스 토큰을 생성한 뒤 응답합니다 그 이후에 클라이언트는 4번과 같이 다시 api를 요청 


236pg 부터 하면됨