로그인 로직 수정.

cks
강석 최 2023-12-22 17:54:45 +09:00
parent c9d8933935
commit 5efe77b066
17 changed files with 165 additions and 75 deletions

View File

@ -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");
});
}

View File

@ -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);

View File

@ -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;}

View File

@ -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);

View File

@ -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');

View File

@ -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(
<Col>
<Col xs={"auto"}>
<input type="button"
className={buttonClass}
value={item.doc_er==='E'?'':'개'}
value={item.doc_er==='E'?'':'개'}
onClick={docInfoSelectorChange}
data-ymd={item.estb_ymd}/>
data-ymd={item.rvsn_ymd}/>
<br/>
<p className={pClass}>{item.doc_yr}</p>
</Col>)
})
headTag.push(<Row className="docInfoRow"><Col className="docInfoTitle">{docCode} {docTitle}</Col>{optionTag}</Row>)
headTag.push(
<Row className="docInfoRow justify-content-start">
<Col xs={"auto"} className="docInfoTitle">{docCode} {docTitle}</Col>
{optionTag}
</Row>
)
}else{
headTag.push(<div>검색된 결과가 없습니다.</div>); // 코드 목록 초기값
}

View File

@ -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?<AiOutlinePlusSquare />:<AiOutlineMinusSquare />;
const icon2 = collapsed?<FcOpenedFolder />:<FcFolder />;
return (

View File

@ -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}/>
<br/>
<p className={pClass}>{item.doc_yr}</p>
</Col>)
@ -256,18 +258,18 @@ function CodeViewer(props) {
}
if(item.error_cd !== null){
if(sessionUserSe === "ADM"){
item.full_content = "<p class='errorText' id='error"+item.cont_type_cd+"'>"+item.error_cd+"</p><br>"+
item.full_content = "<p class='errorText' id='error"+item.doc_cont_seq+"'>"+item.error_cd+"</p><br>"+
"<div class='input-group w-25 d-none errorEditDiv'>" +
"<input type='hidden' class='contTypeCd' value='"+item.cont_type_cd+"' />"+
"<input type='hidden' class='docContSeq' value='"+item.doc_cont_seq+"' />"+
"<input type='text' class='form-control form-control-sm errorCd' value='"+item.error_cd+"'/>"+
"<button class='btn btn-sm btn-primary errorEditSaveBtn'>저장</button>"+
"<button class='btn btn-sm btn-secondary errorEditCancelBtn'>취소</button>"+
"</div>"+
item.full_content;
}else{
item.full_content = "<p class='errorText' id='error"+item.cont_type_cd+"'>"+item.error_cd+"</p><br>"+item.full_content;
item.full_content = "<p class='errorText' id='error"+item.doc_cont_seq+"'>"+item.error_cd+"</p><br>"+item.full_content;
}
optionTag.push(<option value={item.cont_type_cd}>{item.error_cd}</option>)
optionTag.push(<option value={item.doc_cont_seq}>{item.error_cd}</option>)
}
item.full_content = item.full_content+"<hr>"
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;

View File

@ -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<String, Object> accessTokenRefresh(HttpServletRequest request, HttpServletResponse response, @AuthenticationPrincipal UserInfo loginVO){
HashMap<String, Object> 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<String, Object> loginSuccess(HttpServletRequest request, HttpServletResponse response){
return new HashMap<>();
}

View File

@ -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;
}
}

View File

@ -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) );

View File

@ -17,6 +17,5 @@ public class RefreshToken {
private Integer userSeq;
@Indexed
private String refreshToken;
private String remoteAddr;
}

View File

@ -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<String, Object> 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));
}

View File

@ -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;
}

View File

@ -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<String, Object> resultMap = new HashMap<>();

View File

@ -20,8 +20,6 @@ public interface TnDocumentContentRepository extends JpaRepository<TnDocumentCon
@Query(value = "select * from sp_get_recent_full_context_by_content(:docCode, :docPart, :ymd)", nativeQuery = true)
List<StandardCodeContentInterface> spGetRecentFullContextByContent(String docCode, String docPart, String ymd);
Optional<TnDocumentContent> findByContTypeCd(String contTypeCd);
Optional<TnDocumentContent> findByDocInfoSeqAndContTypeCd(Integer docInfoSeq, String contTypeCd);
Optional<TnDocumentContent> findByDocContSeq(Integer docContSeq);
}

View File

@ -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());
}