본문 바로가기
  • 평범한 나의 개발공부 일지
나의 개발 기록/Java /Spring

[JAVA] jwt 생성,발급,유효성검사

by 블랑 블랑 2022. 10. 13.
반응형

먼저 JWT를 관리할 수 있는 JwtUitl 클래스를 생성했다.

 

0. 변수 선언

 

static final String CLAIM_KEY_USERID = "userId";
static final String CLAIM_KEY_USERPW = "userPw";
static final String CLAIM_KEY_USERAUTH = "userAuth";

@Value("#{server['jwt.secret']}")
private String secret;

@Value("#{server['jwt.expiration']}")
private long expiration;

@Value("${jwt.refresh.expiration}")
private long refreshExpiration;

@Value("${token.header_prefix}")
private String prefixHeader;

 

@Value 어노테이션을 사용하여 지정한 properties의 값을 사용할 수 있도록 하였다.

 

  •  server.properties.xml
# JWT PROPERTIES
jwt.header=Authorization
jwt.secret=YXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8gYXRoZW5hLXJvcm8g
jwt.expiration=180
jwt.refresh.expiration=720

 

  • context-properties.xml
<beans:bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<beans:property name="locations">
        	<beans:list>
       			<beans:value>/WEB-INF/properties/server.properties</beans:value> 
        	</beans:list>
        </beans:property>
</beans:bean>

<util:properties id="server" location="/WEB-INF/properties/server.properties"/>

 

 

 

 


(생성 및 발급)

 

 

1. JWT 토큰 생성, 발급
//token 생성(1)-생성
    public String createToken(String userId, String userPw, String userAuth) {
    	Claims claims = Jwts.claims().setSubject(userId);
    	claims.put(CLAIM_KEY_USERID, userId);
    	claims.put(CLAIM_KEY_USERPW, userPw);
    	claims.put(CLAIM_KEY_USERAUTH, userAuth);
        return doCreateToken(claims, expiration);
    }
	
//token 생성(2)-발급
public String doCreateToken(Map<String, Object> claims, long expiration) {
    String jwt =  Jwts.builder()         
        .setClaims(claims) //정보저장
        .setExpiration(new Date(System.currentTimeMillis() + (expiration * 1000 * 60)))
        .signWith(SignatureAlgorithm.HS512, secret) // 사용할 암호화 알고리즘과 signature 에 들어갈 secret값 세팅
        .compact();
    return jwt;
}

 

* 생성메서드를 호출하는 부분 (로그인성공시)

// 사용자-로그인
public HashMap<String, Object> doLogin(HashMap<String, Object> map) {

    HashMap<String, Object> returnMap = new HashMap<String, Object>();
    returnMap.put("isSuccess", "false");
    returnMap.put("errorCode", "ERROR_UNKNOWN");
    HashMap<String, Object> resMap = new HashMap<String, Object>();

    //db token = parameter token && id 같은지 check
    resMap = memberDao.selectLoginCk(map);
    if( resMap != null) {
        //login 정보 일치하면 JWT token 발급
        String paramId = "";
        String paramPw = "";
        String paramAuth = "";
        if( resMap.get("id") != null || resMap.get("pw") != null || resMap.get("atryNm") != null ) {
            paramId = resMap.get("id").toString();
            paramPw = resMap.get("pw").toString();
            paramAuth = resMap.get("atryNm").toString();
        }
        LOGGER.info("jwt!");
        String jwtToken = jwtUtil.createToken(paramId,paramPw,paramAuth);
        returnMap.put("isSuccess", "true");
        returnMap.put("jwtToken", jwtToken);

    }else {
        LOGGER.error("db pw과  parameter pw일치하지 않음  && id일치하지 않음. map:{}" + map);
        returnMap.put("errorCode", "LOGIN_ERROR");
    }

    return returnMap; 
}

 

 

 

 

 


(token 검증)

 

2. 유효한 token인지 검증
① 존재하는 id가 맞는지
② token만료시간 지났는지

 

public int validateToken(String token) {
    	
    	int res = 0;
    	
    	//token에서 id추출
        final String id = getUsernameFromToken(token);
        
        //①token에서 추출한 id가 db에 존재하는지 검증
        res = memberService.selectIdCount(id);
        if( res == 1 ) {
        	//②token만료시간 지났는지 검증
        	if( !isTokenExpired(token) ) {
        		res = 1;
        	}else {
        		res = -1;
        		LOGGER.error("validateToken token검증 : 만료시간이 지남 ");
        	}
        }else {
        	res = -1;
        	LOGGER.error("validateToken token검증 : id가 존재하지 않음.") ;
        }
        
        return res;
    }

 

 

 

   // token으로부터 id를 조회
    public String getUsernameFromToken(String token) {
        String tokenUserId = null;
        try {
            final Claims claims = getClaimsFromToken(token);
            if (claims != null) {
            	if( claims.getId() != null ) tokenUserId = claims.getId();
            	if( claims.getSubject() != null ) tokenUserId = claims.getSubject();
                
            }else {
            	LOGGER.error("claims is null");
            }
        } catch (Exception e) {
        	LOGGER.error("Unhandled exception occurred while invoke getUsernameFromToken(). Reason : [{}]",
        	e.getMessage());
        }
        return tokenUserId;
    }
    
    //token 만료 여부 검증 
    private Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    
    //token 만료시간 조회
    public Date getExpirationDateFromToken(String token) {
    	Date expiration = null;
    	try {
    		final Claims claims = getClaimsFromToken(token);
    		LOGGER.info("############claims###########" + claims);
    			if (claims != null) {
    				//expiration=만료시간
    				expiration = claims.getExpiration();
            	}
    	}catch (Exception e) {
    		LOGGER.error("Unhandled exception occurred while invoke getExpirationDateFromToken(). Reason : [{}]",
    		e.getMessage());

    	}
		return expiration;
    	
    }
    
    //token으로부터 claim 정보 조회
    private Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        } catch (Exception e) {
        	LOGGER.error("Unhandled exception occurred while invoke getClaimsFromToken(). Reason : [{}]",
        	e.getMessage());
        }

        return claims;
    }

 

 

 

 

  • token생성 예제

- 로그인 페이지에서 사용자정보를 보내 사용자정보가 일치하면 토큰을 발급되는 형태로 구성

//로그인정보 일치 확인
resMap = memberDao.selectLoginCk(map);
if( resMap != null) {
    //login 정보 일치하면 JWT token 발급
    String paramId = "";
    String paramPw = "";
    String paramAuth = "";
    if( resMap.get("id") != null || resMap.get("pw") != null || resMap.get("atryNm") != null ) {
        paramId = resMap.get("id").toString();
        paramPw = resMap.get("pw").toString();
        paramAuth = resMap.get("atryNm").toString();
    }
    LOGGER.info("jwt!");
    String jwtToken = jwtUtil.createToken(paramId,paramPw,paramAuth);
}

 

 

 

 

  • token검증 졔제

- 페이지가 이동될때마다 클라이언트에 있는 token을 서버로 보내 유효한지 검증

public HashMap<String, Object> commentSave(@RequestBody HashMap<String, Object> paramMap, @RequestHeader(required = false) HttpHeaders header){

    HashMap<String, Object> tokenMap = new HashMap<String, Object>();
        //cookie에서 token꺼냄
        String token = Utils.getCookie(header);
        if( !"".equals(token) ) {
            //꺼낸token의 유효성 검사, 최종완료시 사용자정보(id, nm, atryNm) 반환
            tokenMap = memberService.tokenValidation(token);
    }
    
}

 

//jwt token검증
public HashMap<String, Object> tokenValidation(String token){

    HashMap<String, Object> infoMap = new HashMap<String, Object>();
    HashMap<String, Object> returnMap = new HashMap<String, Object>();
    returnMap.put("isSuccess", "false");
    returnMap.put("errorCode", "UNKNOWN");

    int res = 0;

    //token검증
    if( !"".equals(token) ) {
        res = jwtUtil.validateToken(token.substring(7));
        if(res==1) {
            //jwt 최종 인증 후 사용자 id, nm, 권한 가져오기
            String id = jwtUtil.getUsernameFromToken(token.substring(7));
            infoMap = memberDao.selectLoginIdNmAuth(id);
            if( infoMap != null && infoMap.get("id") != null && infoMap.get("nm") != null && infoMap.get("atryNm") != null ) {
                String paramId = infoMap.get("id").toString();
                String paramNm = infoMap.get("nm").toString();
                String paramAtryNm = infoMap.get("atryNm").toString();
                returnMap.put("id",paramId);
                returnMap.put("nm",paramNm);
                returnMap.put("atryNm",paramAtryNm);
                returnMap.put("isSuccess", "true");
            }
        }else {
            returnMap.put("errorCode", "JWT_VALIDATE_ERROR");
        }
    }else {
        returnMap.put("errorCode", "JWT_TOKEN_EMP_ERROR");
    }

    return returnMap;
}

 

 

 

 

반응형

댓글