View

로그인 인증 구현 방식에는 ①session cookie 방식과 ②jwt 토큰 방식이 존재한다.  
 

▶️ JWT (Json Web Token)

사용자 인증을 위해 인증에 필요한 정보를 토큰에 담아서 암호화 시켜 사용하는 인터넷 표준 인증 방식 (일종의 확인서)
Header.Payload,Signature 로 구성, 각각 점으로 구분

  • Header : 토큰 유형(JWT)와 사용중인 서명 알고리즘(HMAC, SHA256 등) 포함
{
    "typ": "JWT",
    "alg": "HS256"
}
  • Payload : 등록된 클레임과 개인 클레임
    • 등록된 클레임 : iss(발행자), exp(만료시간), sub(제목), aud(대상)
    • 개인 클레임 : 서로 정보를 공유하기 위해 생성된 사용자 지정 클레임
{
    // 등록된 클레임
    "iss": "chb2005.tistory.com",
    "sub": "123456789",
    "exp": "1659002265",
    // 개인 클레임
    "userName": "changbum",
    "isAdmin": false
}

 

  • Signature : Header, Payload, Secret Key를 합쳐 암호화한 결과값

 

장점

  • 서버는 비밀키만 알고 있으면 되기 때문에 세션 방식과 같이 별도의 인증 저장소가 필요하지 않음
  • 여러개의 서버를 사용하는 대형 서비스같은 경우에 접근 권한가 효율적임 (확장성)

단점

JWT는 HTTP를 통해서 전송하기 때문에 페이로드의 크기가 클수록 데이터 전송에 있어서 비용이 커진다. JWT는 유효기간을 따로 정하지 않는 이상 소멸되지 않기 때문에 장기간 방치시 해킹의 위험이 커진다
 

▶️ 토큰 기반 인증 

요청과 응답에 토큰을 함께 보내 이 사용자가 유효한 사용자인지 검색하는 방법으로
우리가 로그인을 성공하면 Authentication(인증)이 일어나고 서버는 JWT를 제공함
매 요청마다 JWT와 함께 서버에 요청을 보내면 서버는 JWT만 확인하여 Authorization(인가)하게 됨

1️⃣ 클라이언트가 아이디와 비밀번호를 서버에게 전달하며 인증을 요청함
2️⃣,3️⃣ 서버는 아이디와 비밀번호를 통해 유효한 사용자인지 검증하고, 유효한 사용자인 경우 토큰을 생성해서 응답함
4️⃣ 클라이언트는 토큰을 저장해두었다가, 인증이 필요한 api에 요청할 때 Header 내 토큰 정보와 함께 요청함
5️⃣ 서버는 토큰이 유효한지 검증하고, 유효한 경우에는 응답을 해줌

  • 토큰이 존재하지 않을 경우 ➡️ '로그인' 페이지로 리다이렉트시켜 로그인 후 토큰을 발급
  • 토큰이 존재하는 경우 ➡️ 토큰의 만료시간을 확인함
    • 토큰이 만료되었을 때 재발급을 위해 '로그인' 페이지로 리다이렉트시켜 로그인 후 토큰을 재발급
    • 토큰이 유효한 경우 토큰 내의 정보를 확인하고 정상적인 프로세스 진행

 

Access Token, Refresh Token

JWT는 비밀키가 유출되지 않는 이상 토큰을 복호화하지 못하므로 보안에 유리함
하지만 JWT가 수명이 길 경우 탈취당할 경우가 발생할 수 있는데 이를 보안하는 방법이 Access Token과 Refresh Token의 방식이 있음
Access Token(접근) : 사용자를 인증하기 위한 용도
Refresh Token(재발급) : 액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급하기 위해 사용
 
✔️ Access token의 기한은 유효하지만, Access token이 만료되기전에 사용자가 로그인하면 Refresh token을 이용해서 Acess token을 재발급하여 사용기한을 늘릴 수 있다.
✔️ Refresh token이 만료되면 재로그인 요청을 보낸다. 

[출처 : https://velog.io/@ogu1208]

 

▶️ JWT를 사용하여 사용자 인증 구현

1. Maven 라이브러리 추가
2. 로그인 성공했을 때 Authentication Token 객체를 생성하고 검증된 인증 정보로 JWT 토큰 발급

public class JwtEx{
	private static final String SECRET_KEY = "key";
    
    public static void main(String[] args){
    	String token = createJwtToken("userId");	// JWT 토큰 생성
        boolean isValid = validateJwtToken(token);	//생성된 JWT 토큰 검증
    }
    
    public static String createJwtToken(String subject){
    	SecretKey secretKey = Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8));
        String token = Jwts.builder()
                        .setSubject(subject)
                        .setIssuedAt(new Date())
                        .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1h
                        .signWith(secretKey, SignatureAlgorithm.HS256)
                        .compact();
        return token;
    }
    
    public static boolean validateJwtToken(String token){
    	SecretKey secretKey = Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8));
    	try{
        	Jwts.parserBuilder()
            	.setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token);
                return true;	// 서명이 유효한 경우
        }catch(Exception e){
        	return false;	// 서명이 유효하지 않은 경우
        }
    }
}
728x90

'Backend > Java' 카테고리의 다른 글

[Java] 자바 기술 면접 질문/답변  (0) 2023.09.26
Share Link
reply
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31