본문 바로가기
Java

[Java] JWT로 자동 로그인 기능을 위한 API 구현하기

by 코딩초 2023. 11. 17.

* JWT란?

JWT = JSON Web Token

JWT는 웹 애플리케이션 간에 정보를 안전하게 전송하기 위한 표준 방식 중 하나로, 토큰 기반의 인증 시스템에서 보편적으로 사용된다고 한다.

egov환경에서 백엔드 개발 중 API 구현 요구사항을 통해 처음 알게되었다.

내용은 페이지 안에서 버튼을 클릭하면 링크를 통해 다른 사이트로 넘어가야하는데, 이때 넘어간 사이트에서도 같은 사용자 정보로 자동 로그인이 되도록 구현하는 것이다.

1. 서버 :  사용자ID, 비밀번호를 JWT로 base64로 인코딩한 값을  return하는 API 구현

2. 클라이언트 : 해당 API를 호출하여 응답결과의 JWT토큰 값을 decoding 해서 자동 로그인 기능을 구현 

 

* 구현 과정

1.  Maven 종속성 추가

pom.xml 파일에 JWT 라이브러리를 추가

<!--JSON WEB TOKEN(JWT)-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.5</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.11.5</version>
        </dependency>

 

2. jwt 라이브러리 추가

jsonwebtoken라이브러리 그룹을 모두 추가

import io.jsonwebtoken.*;

 

3.  JWT 생성 클래스 구현

//토큰의 만료 시간을 관리
private final int JWT_EXPIRE_TIME = 1000 * 60 * 60 * 1;

public String createJwtSession(User user) throws Exception {
        Map<String, Object> headerMap = new HashMap<String, Object>();
        headerMap.put("typ", "JWT");
        headerMap.put("alg", "HS256");

        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("id", user.getId());
        claims.put("uid", user.getUid());

        // 디코딩된 패스워드 값을 인코딩하여 claims에 추가
        String decodedPassword = new String(Base64.getDecoder().decode(user.getPasswd()));
        claims.put("pw", decodedPassword);

        Date expireTime = new Date();
        expireTime.setTime(expireTime.getTime() + JWT_EXPIRE_TIME);

        JwtBuilder builder = Jwts.builder()
                .setHeader(headerMap)
                .setClaims(claims)
                .setExpiration(expireTime)
                .signWith(createKey(), signatureAlgorithm);

        return builder.compact();
}
       
    
public Claims checkJwt(String jwt) throws Exception {
        try {
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(baseKey))
                    .build()
                    .parseClaimsJws(jwt)
                    .getBody();
            System.out.println("Id : " + claims.get("id"));
            System.out.println("Name : " + claims.get("name"));

            return claims;
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            throw new Exception("Expired JWT");
        } catch (JwtException e) {
            e.printStackTrace();
            throw new Exception("Invalid JWT");
        }
   }

 

4. JWT 반환하는  API 구현

현재 로그인한 사용자의 JWT 토큰을 검증하고,  해당 사용자의 정보와 토큰의 디코딩 결과를 포함한 응답을 반환하도록 구현

@GetMapping(value = "/sessionInfo")
    public ResponseVO aip(HttpServletRequest request) throws Exception {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            Claims claims = null;
            for (Cookie cookie : request.getCookies()) {
                if (cookie.getName().equals("jwt")) {
                    claims = checkJwt(cookie.getValue());
                    break;
                }
            }

            if (claims != null) {
                ResponseVO obj = commonService.isUserNull(request);
                if (obj.getStatus() == Constants.STATUS_NOK)
                    return obj;

                User user = (User) obj.getResult();

                JSONObject json = new JSONObject();
                json.put("loginSession", createJwtSession(user));

                obj.setMessage("jwt created");
                obj.setResult(json);

                return obj;
            }
        }
        return null;
    }