Merge branch 'dev_tymeleaf' of http://git.icomsys.co.kr/JANGWONSEOK/cinnamon-ui-v2 into dev_tymeleaf
# Conflicts: # .gitignoredev_tymeleaf
commit
160f5135f5
Binary file not shown.
Binary file not shown.
@ -0,0 +1,15 @@
|
|||||||
|
package com.icomsys.main_vm.biz.common.login;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CinnamonToken {
|
||||||
|
|
||||||
|
private String grantType;
|
||||||
|
private String accessToken;
|
||||||
|
private String refreshToken;
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
package com.icomsys.main_vm.biz.common.login;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
import com.icomsys.main_vm.db.jpa.entity.system.TbBotUser;
|
||||||
|
import com.icomsys.main_vm.db.jpa.repo.system.TbUserAuthGroupRepo;
|
||||||
|
import io.jsonwebtoken.*;
|
||||||
|
import io.jsonwebtoken.io.Decoders;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class TokenProvider {
|
||||||
|
private final TbUserAuthGroupRepo tbUserAuthGroupRepo;
|
||||||
|
|
||||||
|
private static final long ACCESS_TOKEN_EXPIRE_TIME = 20 * 60 * 1000L;
|
||||||
|
private static final long REFRESH_TOKEN_EXPIRE_TIME = 24 * 60 * 60 * 1000L;
|
||||||
|
|
||||||
|
private final Key key;
|
||||||
|
|
||||||
|
public TokenProvider(@Value("${spring.jwt.secret}") String secretKey, TbUserAuthGroupRepo tbUserAuthGroupRepo) {
|
||||||
|
this.tbUserAuthGroupRepo = tbUserAuthGroupRepo;
|
||||||
|
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
|
||||||
|
this.key = Keys.hmacShaKeyFor(keyBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(Authentication authentication, TbBotUser user) throws JsonProcessingException {
|
||||||
|
// 권한 가져오기
|
||||||
|
String authorities = authentication.getAuthorities().stream()
|
||||||
|
.map(GrantedAuthority::getAuthority)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
|
||||||
|
long now = (new Date()).getTime();
|
||||||
|
// Access Token 생성
|
||||||
|
// Todo: Access Token 필요정보 추가 개발 필요
|
||||||
|
Date accessTokenExpiresIn = new Date(now + ACCESS_TOKEN_EXPIRE_TIME); // Todo: Access Token 만료 기간 설정 파일 추가
|
||||||
|
|
||||||
|
Claims claims = Jwts.claims()
|
||||||
|
.setSubject(authentication.getName())
|
||||||
|
.setExpiration(accessTokenExpiresIn);
|
||||||
|
|
||||||
|
claims.put("auth", authorities);
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
// claims.put("UserVO", mapper.registerModule(new JavaTimeModule()).writeValueAsString(user.toUserVO()));
|
||||||
|
try {
|
||||||
|
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
|
|
||||||
|
LocalDateTimeSerializer localDateTimeSerializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
javaTimeModule.addSerializer(LocalDateTime.class, localDateTimeSerializer);
|
||||||
|
|
||||||
|
// claims.put("UserVO", mapper.registerModule(javaTimeModule).readValue(user.toUserVO(), UserVo.class));
|
||||||
|
claims.put("UserVO", mapper.registerModule(javaTimeModule).writeValueAsString(user.toUserVO()));
|
||||||
|
// claims.put("PolicyList", tbUserAuthGroupRepo.userPolicyListSelect(user.getUserSeq(), user.getLastUseServiceGroup()));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
String accessToken = Jwts.builder()
|
||||||
|
.setSubject(authentication.getName())
|
||||||
|
.setClaims(claims)
|
||||||
|
.setExpiration(accessTokenExpiresIn)
|
||||||
|
.signWith(key, SignatureAlgorithm.HS256)
|
||||||
|
.compact();
|
||||||
|
|
||||||
|
// Refresh Token 생성
|
||||||
|
String refreshToken = Jwts.builder()
|
||||||
|
.setExpiration(new Date(now + REFRESH_TOKEN_EXPIRE_TIME)) // Todo: Refresh Token 만료 기간 설정 파일에 추가
|
||||||
|
.signWith(key, SignatureAlgorithm.HS256)
|
||||||
|
.compact();
|
||||||
|
|
||||||
|
CinnamonToken token = CinnamonToken.builder()
|
||||||
|
.grantType("Bearer")
|
||||||
|
.accessToken(accessToken)
|
||||||
|
.refreshToken(refreshToken)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JWT 토큰을 복호화하여 토큰에 들어있는 정보를 꺼내는 메서드
|
||||||
|
public Authentication getAuthentication(String accessToken) {
|
||||||
|
// 토큰 복호화
|
||||||
|
Claims claims = parseClaims(accessToken);
|
||||||
|
|
||||||
|
// Todo: 권한 관련 정보 처리
|
||||||
|
if (claims.get("auth") == null) {
|
||||||
|
throw new RuntimeException("권한 정보가 없는 토큰입니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: 사용자 정보와 권한 관련 정보를 읽어와 리턴
|
||||||
|
|
||||||
|
// 클레임에서 권한 정보 가져오기
|
||||||
|
Collection<? extends GrantedAuthority> authorities =
|
||||||
|
Arrays.stream(claims.get("auth").toString().split(","))
|
||||||
|
.map(SimpleGrantedAuthority::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// UserDetails 객체를 만들어서 Authentication 리턴
|
||||||
|
// UserDetails principal = new User(claims.getSubject(), "", authorities);
|
||||||
|
return new UsernamePasswordAuthenticationToken(/*principal*/ "", "", authorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 토큰 정보를 검증하는 메서드
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
// Todo: 내부 토큰 사용 정책에 따라 추후 수정 필요!!
|
||||||
|
try {
|
||||||
|
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
|
||||||
|
return true;
|
||||||
|
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
|
||||||
|
log.info("Invalid JWT Token", e);
|
||||||
|
} catch (ExpiredJwtException e) {
|
||||||
|
log.info("Expired JWT Token", e);
|
||||||
|
} catch (UnsupportedJwtException e) {
|
||||||
|
log.info("Unsupported JWT Token", e);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.info("JWT claims string is empty.", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Claims parseClaims(String accessToken) {
|
||||||
|
try {
|
||||||
|
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(accessToken).getBody();
|
||||||
|
} catch (ExpiredJwtException e) {
|
||||||
|
return e.getClaims();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue