반응형
먼저 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;
}
반응형
'나의 개발 기록 > Java /Spring' 카테고리의 다른 글
[JSTL] 날짜를 숫자로, 날짜를 포맷하기 (0) | 2022.11.18 |
---|---|
[Java] 현재날짜, 현재날짜/시간 구하기 (0) | 2022.11.18 |
[JAVA] 전자정부프레임워크 util:properties로 프로퍼티 사용하기 (feat. @value로 값출력) (0) | 2022.09.14 |
[전자정부프레임워크] egov commons-io 라이브러리 추가 (0) | 2022.09.07 |
전자정부프레임워크에서 *.do 확장자 없이 접근하도록 수정해보기 (0) | 2022.08.18 |
댓글