diff --git a/egovframe-template-simple-react-contribution/src/api/egovFetch.js b/egovframe-template-simple-react-contribution/src/api/egovFetch.js index d1f9ded..4d3e989 100644 --- a/egovframe-template-simple-react-contribution/src/api/egovFetch.js +++ b/egovframe-template-simple-react-contribution/src/api/egovFetch.js @@ -16,38 +16,36 @@ export function requestFetch(url, requestOptions, handler, errorHandler) { console.log("requestFetch [requestOption] : ", requestOptions); // Login 했을경우 JWT 설정 - const jToken = getLocalItem('jToken'); - const sessionUser = parseJwt(jToken); + const accessToken = getLocalItem('accessToken'); + const sessionUser = parseJwt(accessToken); const sessionUserId = sessionUser?.id || null; const refreshToken = getLocalItem('refreshToken'); if(sessionUserId != null){ if( !requestOptions['headers'] ) requestOptions['headers']={} if( !requestOptions['headers']['Authorization'] ) requestOptions['headers']['Authorization']=null; - requestOptions['headers']['Authorization'] = jToken; + requestOptions['headers']['Authorization'] = accessToken; } - - //CORS ISSUE 로 인한 조치 - origin 및 credentials 추가 + //CORS ISSUE 로 인한 조치 - origin 및 credentials 추가 // origin 추가 if (!requestOptions['origin']) { requestOptions = { ...requestOptions, origin: SERVER_URL }; } - // credentials 추가 + // credentials 추가 if (!requestOptions['credentials']) { requestOptions = { ...requestOptions, credentials: 'include' }; } fetch(SERVER_URL + url, requestOptions) .then(response => {// response Stream. Not completion object - //console.log("requestFetch [Response Stream] ", response); + //console.log("requestFetch [Response Stream] ", response); return response.json(); }) .then((resp) => { if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) { - alert("Login Alert"); //index.jsx라우터파일에 jwtAuthentication 함수로 공통 인증을 사용하는 코드 추가로 alert 원상복구 - setSessionItem('loginUser', {"id":""}); - window.location.href = URL.LOGIN; - return false; + //accessToken 갱신 요청 + accessTokenRefresh(url, requestOptions, handler, errorHandler); + return resp; } else { return resp; } @@ -79,4 +77,60 @@ export function requestFetch(url, requestOptions, handler, errorHandler) { console.log("requestFetch finally end"); console.groupEnd("requestFetch"); }); + +} + +function accessTokenRefresh(url, requestOptions, handler, errorHandler){ + requestOptions['headers']['Authorization'] = getLocalItem('refreshToken'); + if (!requestOptions['origin']) { + requestOptions = { ...requestOptions, origin: SERVER_URL }; + } + if (!requestOptions['credentials']) { + requestOptions = { ...requestOptions, credentials: 'include' }; + } + + fetch(SERVER_URL + "/auth/accessTokenRefresh", requestOptions) + .then(response => { + return response.json(); + }) + .then((resp) => { + if(resp?.accessToken != null){ + setLocalItem('accessToken', resp.accessToken); + requestFetch(url, requestOptions, handler, errorHandler); + }else{ + // 갱신 실패 + alert("로그인이 해제되었습니다."); + // index.jsx라우터파일에 jwtAuthentication 함수로 공통 인증을 사용하는 코드 추가로 alert 원상복구 + setLocalItem('accessToken', null); + setLocalItem('refreshToken', null); + window.location.href = URL.LOGIN; + } + }) + .then((resp) => { + console.groupCollapsed("requestFetch.then()"); + console.log("requestFetch [response] ", resp); + if (typeof handler === 'function') { + handler(resp); + } else { + console.log('egov fetch handler not assigned!'); + } + console.groupEnd("requestFetch.then()"); + }) + .catch(error => { + console.error('There was an error!', error); + if (error === 'TypeError: Failed to fetch') { + alert("서버와의 연결이 원활하지 않습니다. 서버를 확인하세요."); + } + + if (typeof errorHandler === 'function') { + errorHandler(error); + } else { + console.error('egov error handler not assigned!'); + alert("ERR : " + error.message); + } + }) + .finally(() => { + console.log("requestFetch finally end"); + console.groupEnd("requestFetch"); + }); } \ No newline at end of file diff --git a/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx b/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx index 71beb2e..3d79193 100644 --- a/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx +++ b/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx @@ -13,8 +13,8 @@ function EgovHeader({ loginUser, onChangeLogin }) { console.group("EgovHeader"); console.log("[Start] EgovHeader ------------------------------"); - const jToken = getLocalItem('jToken'); - const userInfo = parseJwt(jToken); + const accessToken = getLocalItem('accessToken'); + const userInfo = parseJwt(accessToken); const sessionUserId = userInfo?.id; const sessionUserSe = userInfo?.userSe; @@ -38,12 +38,11 @@ function EgovHeader({ loginUser, onChangeLogin }) { } EgovNet.requestFetch(logOutUrl, requestOptions, function (resp) { - debugger console.log("===>>> logout resp= ", resp); if (parseInt(resp.resultCode) === parseInt(CODE.RCV_SUCCESS)) { onChangeLogin({ loginVO: {} }); setLocalItem('loginUser', {"id":""}); - setLocalItem('jToken', null); + setLocalItem('accessToken', null); setLocalItem('refreshToken', null); window.alert("로그아웃되었습니다!"); navigate(URL.MAIN); diff --git a/egovframe-template-simple-react-contribution/src/css/page.css b/egovframe-template-simple-react-contribution/src/css/page.css index 2650b6e..77cd9e0 100644 --- a/egovframe-template-simple-react-contribution/src/css/page.css +++ b/egovframe-template-simple-react-contribution/src/css/page.css @@ -342,6 +342,6 @@ .modalYearInfoActive{color: #0d6efd} .modalDocInfoBtn{--bs-btn-padding-y: 0.1rem;--bs-btn-padding-x: 0.25rem;--bs-btn-font-size: 0.7rem; filter: grayscale(100%);} .modalDocInfoActive{filter: grayscale(0%);} -.docInfoRow > .col{--bs-gutter-x: 0.5rem;} +.docInfoRow > div{--bs-gutter-x: 0.5rem;} .bookmarkModalHeader{--bs-modal-title-line-height:1;} .optionBtn{--bs-btn-padding-y: 0.1rem;--bs-btn-padding-x: 0.25rem;--bs-btn-font-size: 0.7rem; margin-right: 7px;} \ No newline at end of file diff --git a/egovframe-template-simple-react-contribution/src/pages/login/EgovLoginContent.jsx b/egovframe-template-simple-react-contribution/src/pages/login/EgovLoginContent.jsx index e254726..c17f4d7 100644 --- a/egovframe-template-simple-react-contribution/src/pages/login/EgovLoginContent.jsx +++ b/egovframe-template-simple-react-contribution/src/pages/login/EgovLoginContent.jsx @@ -74,14 +74,13 @@ function EgovLoginContent(props) { EgovNet.requestFetch(loginUrl, requestOptions, (resp) => { - let jToken = resp?.jToken || null; - let resultVO = parseJwt(jToken); + let accessToken = resp?.accessToken || null; + let resultVO = parseJwt(accessToken); let refreshToken = resp?.refreshToken || null; - // setSessionItem('jToken', jToken); - setLocalItem('jToken', jToken); + // setSessionItem('accessToken', accessToken); + setLocalItem('accessToken', accessToken); setLocalItem('refreshToken', refreshToken); - debugger if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) { // setSessionItem('loginUser', resultVO); props.onChangeLogin(resultVO); diff --git a/egovframe-template-simple-react-contribution/src/pages/login/join/Join.jsx b/egovframe-template-simple-react-contribution/src/pages/login/join/Join.jsx index 29b18db..40b7829 100644 --- a/egovframe-template-simple-react-contribution/src/pages/login/join/Join.jsx +++ b/egovframe-template-simple-react-contribution/src/pages/login/join/Join.jsx @@ -45,9 +45,9 @@ function Join(props) { requestOptions, (resp) => { let resultVO = resp.resultVO; - let jToken = resp?.jToken || null; + let accessToken = resp?.accessToken || null; - setSessionItem('jToken', jToken); + setLocalItem('accessToken', accessToken); if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) { alert(resp.resultMessage); navigate('/login'); diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/BookmarkModal.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/BookmarkModal.js index 0c4c746..d60895d 100644 --- a/egovframe-template-simple-react-contribution/src/pages/standardCode/BookmarkModal.js +++ b/egovframe-template-simple-react-contribution/src/pages/standardCode/BookmarkModal.js @@ -80,26 +80,31 @@ const BookmarkModal = ({docCode, docPart, ymd}) => { let buttonClass = "btn btn-sm modalDocInfoBtn " let pClass = "modalYearInfo "; if(item.doc_er === 'E'){ - buttonClass += "btn-outline-success " + buttonClass += "btn-success " }else{ - buttonClass += "btn-outline-primary " + buttonClass += "btn-primary " } if(index === activeIndex){ pClass += "modalYearInfoActive" buttonClass += "modalDocInfoActive" } optionTag.push( - + + data-ymd={item.rvsn_ymd}/>

{item.doc_yr}

) }) - headTag.push({docCode} {docTitle}{optionTag}) + headTag.push( + + {docCode} {docTitle} + {optionTag} + + ) }else{ headTag.push(
검색된 결과가 없습니다.
); // 코드 목록 초기값 } diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/SbItem.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/SbItem.js index 289556d..8912f76 100644 --- a/egovframe-template-simple-react-contribution/src/pages/standardCode/SbItem.js +++ b/egovframe-template-simple-react-contribution/src/pages/standardCode/SbItem.js @@ -22,7 +22,7 @@ const SbItem = ({item, openDocCode, updateDocCode}) => { nextOpenDoc.className = nextOpenDoc.className+' openDoc'; } - if(item.childrens.length > 0){ + if(item.group_yn==='Y'){ const icon1 = collapsed?:; const icon2 = collapsed?:; return ( diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer.js index f8aeb09..6c377c2 100644 --- a/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer.js +++ b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer.js @@ -30,7 +30,7 @@ function CodeViewer(props) { const [bookMarkModal, setBookMarkModal] = useState(); - const sessionUser = parseJwt(getLocalItem('jToken')); + const sessionUser = parseJwt(getLocalItem('accessToken')); const sessionUserSe = sessionUser?.userSe; const handleClose = () => setShow(false); @@ -141,7 +141,9 @@ function CodeViewer(props) { className={buttonClass} value={item.doc_er==='E'?'제':'개'} onClick={docInfoSelectorChange} - data-ymd={item.rvsn_ymd} data-doccode={item.kcsc_cd}/> + data-ymd={item.rvsn_ymd} + data-doccode={item.kcsc_cd} + data-docinfoseq={item.doc_info_seq}/>

{item.doc_yr}

) @@ -256,18 +258,18 @@ function CodeViewer(props) { } if(item.error_cd !== null){ if(sessionUserSe === "ADM"){ - item.full_content = "

"+item.error_cd+"


"+ + item.full_content = "

"+item.error_cd+"


"+ "
" + - ""+ + ""+ ""+ ""+ ""+ "
"+ item.full_content; }else{ - item.full_content = "

"+item.error_cd+"


"+item.full_content; + item.full_content = "

"+item.error_cd+"


"+item.full_content; } - optionTag.push() + optionTag.push() } item.full_content = item.full_content+"
" detailTag.push( @@ -368,8 +370,7 @@ function CodeViewer(props) { saveBtn.onclick = (e) => { const errorEditDiv = e.target.parentElement; const content = { - docInfoSeq: document.querySelector("#docInfoSelector").value, - contTypeCd: errorEditDiv.querySelector(".contTypeCd").value, + docContSeq: errorEditDiv.querySelector(".docContSeq").value, errorCd: errorEditDiv.querySelector(".errorCd").value } saveErrorCd(content, errorEditDiv) @@ -399,7 +400,7 @@ function CodeViewer(props) { function saveErrorCd(content, errorEditDiv){ EgovNet.requestFetch( - '/standardCode/saveErrorCd.do', + '/standardCode/auth/saveErrorCd.do', { method: "POST", headers: { @@ -411,6 +412,8 @@ function CodeViewer(props) { if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) { alert("저장되었습니다.") errorEditDiv.parentElement.querySelector(".errorText").innerText = content.errorCd + }else if(Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)){ + console.log("토큰 갱신중.") }else{ alert("저장에 실패하였습니다.") } @@ -468,8 +471,8 @@ function CodeViewer(props) { } CodeViewer.defaultProps = { - docCode: 'KDS 24 14 21', - docName: '교량 설계 일반사항(한계상태설계법)' + docCode: 'KCS 24 31 10', + docName: '용접(한계상태설계법)' } export default CodeViewer; diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/auth/EgovLoginApiController.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/auth/EgovLoginApiController.java index 00acfea..6a4334d 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/auth/EgovLoginApiController.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/auth/EgovLoginApiController.java @@ -1,5 +1,6 @@ package com.dbnt.kcscbackend.auth; +import com.dbnt.kcscbackend.auth.entity.UserInfo; import com.dbnt.kcscbackend.auth.service.EgovLoginService; import com.dbnt.kcscbackend.config.common.BaseController; import com.dbnt.kcscbackend.auth.entity.LoginVO; @@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.ui.ModelMap; import org.springframework.validation.Errors; @@ -48,6 +50,7 @@ import java.util.List; @Slf4j @RestController +@RequiredArgsConstructor @RequestMapping("/auth") @Tag(name="EgovLoginApiController",description = "로그인 관련") public class EgovLoginApiController extends BaseController { @@ -56,6 +59,8 @@ public class EgovLoginApiController extends BaseController { @Resource(name = "loginService") private EgovLoginService loginService; + private final EgovJwtTokenUtil egovJwtTokenUtil; + /** EgovMessageSource */ @Resource(name = "egovMessageSource") EgovMessageSource egovMessageSource; @@ -83,26 +88,39 @@ public class EgovLoginApiController extends BaseController { msg.append(error.getDefaultMessage()); msg.append("\n"); } - resultMap.put("resultCode", "300"); + resultMap.put("resultCode", ResponseCode.SAVE_ERROR.getCode()); resultMap.put("resultMessage", msg.toString()); }else if(!loginVO.getPassword().equals(loginVO.getPasswordChk())){ - resultMap.put("resultCode", "300"); + resultMap.put("resultCode", ResponseCode.SAVE_ERROR.getCode()); resultMap.put("resultMessage", "비밀번호 확인이 잘못 입력되었습니다."); }else{ Integer insertResult = loginService.insertUser(loginVO); if(insertResult!=null){ - resultMap.put("resultCode", "200"); + resultMap.put("resultCode", ResponseCode.SUCCESS.getCode()); resultMap.put("resultMessage", "저장 되었습니다."); }else{ - resultMap.put("resultCode", "300"); + resultMap.put("resultCode", ResponseCode.SAVE_ERROR.getCode()); resultMap.put("resultMessage", "저장에 실패하였습니다."); } } return resultMap; } - @RequestMapping("/auth/loginSuccess") + @RequestMapping("/accessTokenRefresh") + public HashMap accessTokenRefresh(HttpServletRequest request, HttpServletResponse response, @AuthenticationPrincipal UserInfo loginVO){ + HashMap resultMap = new HashMap<>(); + String token = egovJwtTokenUtil.accessTokenRefresh(request.getHeader("Authorization")); + if(token!=null){ + resultMap.put("resultCode", ResponseCode.SUCCESS.getCode()); + resultMap.put("accessToken", token); + }else{ + resultMap.put("resultCode", ResponseCode.AUTH_ERROR.getCode()); + } + return resultMap; + } + + @RequestMapping("/loginSuccess") public HashMap loginSuccess(HttpServletRequest request, HttpServletResponse response){ return new HashMap<>(); } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/EgovJwtTokenUtil.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/EgovJwtTokenUtil.java index a254d7e..c6b1dd2 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/EgovJwtTokenUtil.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/EgovJwtTokenUtil.java @@ -53,6 +53,8 @@ public class EgovJwtTokenUtil implements Serializable{ public static final String SECRET_KEY = EgovProperties.getProperty("Globals.jwt.secret"); private final RefreshTokenRepository refreshTokenRepository; + public static final long JWT_ACCESS_VALID_TIME = (30*60*1000); //엑세스 토큰의 유효시간 설정, 30분 + public static final long JWT_REFRESH_VALID_TIME = (60*60*24*14*1000); //리프레시 토큰의 유효시간 설정, 2주 //retrieve username from jwt token @@ -69,8 +71,7 @@ public class EgovJwtTokenUtil implements Serializable{ return claims.get(type).toString(); } public Claims getClaimFromToken(String token) { - final Claims claims = getAllClaimsFromToken(token); - return claims; + return getAllClaimsFromToken(token); } //for retrieveing any information from token we will need the secret key @@ -104,15 +105,31 @@ public class EgovJwtTokenUtil implements Serializable{ return builder.compact(); } - public String generateAccessToken(UserInfo loginVO, String remoteAddr, Long sec) { - return generateToken(loginVO, remoteAddr, sec); + public String generateAccessToken(UserInfo loginVO, String remoteAddr) { + return generateToken(loginVO, remoteAddr, JWT_ACCESS_VALID_TIME); } @Transactional - public String generateRefreshTokenToken(UserInfo loginVO, String remoteAddr, Long sec){ - RefreshToken refreshToken = new RefreshToken(loginVO.getUserSeq(), generateToken(loginVO, remoteAddr, sec), remoteAddr); + public String generateRefreshTokenToken(UserInfo loginVO, String remoteAddr){ + String token = generateToken(loginVO, remoteAddr, JWT_REFRESH_VALID_TIME); + RefreshToken refreshToken = new RefreshToken(loginVO.getUserSeq(), token); refreshTokenRepository.save(refreshToken); return refreshToken.getRefreshToken(); } + public String accessTokenRefresh(String token){ + RefreshToken refreshToken = refreshTokenRepository.findByRefreshToken(token).orElse(null); + if(refreshToken!=null){ + Claims claims = getClaimFromToken(refreshToken.getRefreshToken()); + JwtBuilder builder = Jwts.builder() + .setClaims(claims) + .setSubject("Authorization") + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + JWT_ACCESS_VALID_TIME)) + .signWith(Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8)), SignatureAlgorithm.HS512); + return builder.compact(); + } + return null; + } + } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/JwtAuthenticationFilter.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/JwtAuthenticationFilter.java index 806f247..0615647 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/JwtAuthenticationFilter.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/JwtAuthenticationFilter.java @@ -44,7 +44,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { // step 1. request header에서 토큰을 가져온다. String jwtToken = EgovStringUtil.isNullToString(req.getHeader(HEADER_STRING)); - // step 2. 토큰에 내용이 있는지 확인해서 id값을 가져옴 // Exception 핸들링 추가처리 (토큰 유효성, 토큰 변조 여부, 토큰 만료여부) // 내부적으로 parse하는 과정에서 해당 여부들이 검증됨 @@ -60,6 +59,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { logger.debug("===>>> id = " + id); } catch (IllegalArgumentException | ExpiredJwtException | MalformedJwtException | UnsupportedJwtException | SignatureException e) { logger.debug("Unable to verify JWT Token: " + e.getMessage()); + req.setAttribute("errorType", e.getClass().getName()); + req.setAttribute("errorMsg", e.getMessage()); verificationFlag = false; } @@ -68,7 +69,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { logger.debug("jwtToken validated"); loginVO.setId(id); loginVO.setUserSe( jwtTokenUtil.getUserSeFromToken(jwtToken) ); - loginVO.setUniqId( jwtTokenUtil.getInfoFromToken("uniqId",jwtToken) ); +// loginVO.setUniqId( jwtTokenUtil.getInfoFromToken("uniqId",jwtToken) ); // loginVO.setOrgnztId( jwtTokenUtil.getInfoFromToken("orgnztId",jwtToken) ); // loginVO.setName( jwtTokenUtil.getInfoFromToken("name",jwtToken) ); diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/redis/RefreshToken.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/redis/RefreshToken.java index 2916664..572d18b 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/redis/RefreshToken.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/jwt/redis/RefreshToken.java @@ -17,6 +17,5 @@ public class RefreshToken { private Integer userSeq; @Indexed private String refreshToken; - private String remoteAddr; } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/CustomUrlAuthenticationSuccessHandler.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/CustomUrlAuthenticationSuccessHandler.java index 941ebcb..9e45e94 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/CustomUrlAuthenticationSuccessHandler.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/CustomUrlAuthenticationSuccessHandler.java @@ -29,8 +29,6 @@ public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticati private final EgovJwtTokenUtil jwtTokenUtil; private RequestCache requestCache = new HttpSessionRequestCache(); - public static final long JWT_ACCESS_VALID_TIME = (30*60*1000); //엑세스 토큰의 유효시간 설정, 30분 - public static final long JWT_REFRESH_VALID_TIME = (60*60*24*14*1000); //리프레시 토큰의 유효시간 설정, 2주 @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, @@ -55,16 +53,15 @@ public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticati MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); MediaType jsonMimeType = MediaType.APPLICATION_JSON; - String jwtToken = jwtTokenUtil.generateAccessToken(securityUser, request.getRemoteAddr(), JWT_ACCESS_VALID_TIME); - String refreshToken = jwtTokenUtil.generateRefreshTokenToken(securityUser, request.getRemoteAddr(), JWT_REFRESH_VALID_TIME); + String accessToken = jwtTokenUtil.generateAccessToken(securityUser, request.getRemoteAddr()); + String refreshToken = jwtTokenUtil.generateRefreshTokenToken(securityUser, request.getRemoteAddr()); HashMap resultMap = new HashMap<>(); resultMap.put("resultCode", "200"); - resultMap.put("jToken", jwtToken); + resultMap.put("accessToken", accessToken); resultMap.put("refreshToken", refreshToken); - response.addHeader("Authorization", "BEARER "+jwtToken); - Cookie refreshTokenCookie = new Cookie("refreshToken", refreshToken); - refreshTokenCookie.setMaxAge((int)JWT_REFRESH_VALID_TIME/1000); - response.addCookie(refreshTokenCookie); +// response.addHeader("Authorization", "BEARER "+accessToken); +// Cookie refreshTokenCookie = new Cookie("refreshToken", refreshToken); +// response.addCookie(refreshTokenCookie); if (jsonConverter.canWrite(resultMap.getClass(), jsonMimeType)) { jsonConverter.write(resultMap, jsonMimeType, new ServletServerHttpResponse(response)); } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/SecurityConfig.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/SecurityConfig.java index 944fa06..0f5213d 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/SecurityConfig.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/security/SecurityConfig.java @@ -6,7 +6,6 @@ import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationFilter; import com.dbnt.kcscbackend.config.jwt.redis.RefreshTokenRepository; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; @@ -49,7 +48,7 @@ public class SecurityConfig { @Resource(name = "loginService") private UserDetailsService loginService; private final ObjectMapper objectMapper; - private final RefreshTokenRepository refreshTokenRepository; + private final EgovJwtTokenUtil egovJwtTokenUtil; //Http Methpd : Get 인증예외 List private String[] AUTH_GET_WHITELIST = { @@ -63,6 +62,7 @@ public class SecurityConfig { "/", "/auth/login", "/login", + "/auth/accessTokenRefresh", // jwt accessToken 갱신 "/auth/join",//회원가입 "/cmm/main/**.do", // 메인페이지 "/cmm/fms/FileDown.do", //파일 다운로드 @@ -123,12 +123,13 @@ public class SecurityConfig { http.cors().and().addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class) .exceptionHandling(exceptionHandlingConfigurer -> - exceptionHandlingConfigurer - .authenticationEntryPoint(new JwtAuthenticationEntryPoint()) + exceptionHandlingConfigurer.authenticationEntryPoint(new JwtAuthenticationEntryPoint()) ); http.addFilterBefore(jsonUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); + http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/auth/logout")).logoutSuccessHandler(new CustomLogoutSuccessHandler()); + return http.build(); } @@ -141,8 +142,7 @@ public class SecurityConfig { @Bean public JsonAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() { - EgovJwtTokenUtil jwtTokenUtil = new EgovJwtTokenUtil(refreshTokenRepository); - JsonAuthenticationFilter jsonAuthenticationFilter = new JsonAuthenticationFilter(objectMapper, new CustomUrlAuthenticationSuccessHandler(jwtTokenUtil), loginFailureHandler()); + JsonAuthenticationFilter jsonAuthenticationFilter = new JsonAuthenticationFilter(objectMapper, new CustomUrlAuthenticationSuccessHandler(egovJwtTokenUtil), loginFailureHandler()); jsonAuthenticationFilter.setAuthenticationManager(authenticationManager()); return jsonAuthenticationFilter; } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/StandardCodeController.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/StandardCodeController.java index 5ba3c82..2deee3f 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/StandardCodeController.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/StandardCodeController.java @@ -119,7 +119,7 @@ public class StandardCodeController extends BaseController { @ApiResponse(responseCode = "303", description = "만료된 토큰"), @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님") }) - @RequestMapping(method = RequestMethod.POST, value = "/saveErrorCd.do", consumes = MediaType.APPLICATION_JSON_VALUE) + @RequestMapping(method = RequestMethod.POST, value = "/auth/saveErrorCd.do", consumes = MediaType.APPLICATION_JSON_VALUE) public ResultVO saveErrorCd(@RequestBody TnDocumentContent content, @AuthenticationPrincipal LoginVO user, HttpServletRequest req) throws Exception { ResultVO resultVO = new ResultVO(); Map resultMap = new HashMap<>(); diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/repository/TnDocumentContentRepository.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/repository/TnDocumentContentRepository.java index 4e5b25b..a33c814 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/repository/TnDocumentContentRepository.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/repository/TnDocumentContentRepository.java @@ -20,8 +20,6 @@ public interface TnDocumentContentRepository extends JpaRepository spGetRecentFullContextByContent(String docCode, String docPart, String ymd); - Optional findByContTypeCd(String contTypeCd); - - Optional findByDocInfoSeqAndContTypeCd(Integer docInfoSeq, String contTypeCd); + Optional findByDocContSeq(Integer docContSeq); } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/service/StandardCodeService.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/service/StandardCodeService.java index 4012e4e..e76b145 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/service/StandardCodeService.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/standardCode/service/StandardCodeService.java @@ -26,7 +26,7 @@ public class StandardCodeService extends EgovAbstractServiceImpl { @Transactional public void saveErrorCd(TnDocumentContent content) { - TnDocumentContent saveContent = tnDocumentContentRepository.findByDocInfoSeqAndContTypeCd(content.getDocInfoSeq(), content.getContTypeCd()).orElse(null); + TnDocumentContent saveContent = tnDocumentContentRepository.findByDocContSeq(content.getDocContSeq()).orElse(null); if(saveContent!=null){ saveContent.setErrorCd(content.getErrorCd()); }