diff --git a/src/main/java/nlib/cmm/web/NotificationController.java b/src/main/java/nlib/cmm/web/NotificationController.java index 6b638b74..c3d691b7 100644 --- a/src/main/java/nlib/cmm/web/NotificationController.java +++ b/src/main/java/nlib/cmm/web/NotificationController.java @@ -11,6 +11,7 @@ import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -106,11 +107,13 @@ public class NotificationController extends NlibCommonController { * @param req * @return */ + @Secured("ROLE_USER") @RequestMapping(value="/cmm/listNotificationsAjax.do") public ResponseEntity listNotificationsAjax(HttpServletRequest req, - Authentication authentication, @RequestBody Map paramMap) throws Exception { + Authentication authentication, @RequestBody(required = false) Map paramMap) throws Exception { String mbInfoId = getMbInfoId(req); + if(paramMap == null) paramMap = new HashMap(); int pageIndex = StringUtil.toNumber(paramMap.get("pageIndex"), 1); int pageSize = StringUtil.toNumber(paramMap.get("pageSize"), DEFUALT_PAGE_SIZE); diff --git a/src/main/java/nlib/col/web/ReadController.java b/src/main/java/nlib/col/web/ReadController.java index 95301fd7..d095d6e6 100644 --- a/src/main/java/nlib/col/web/ReadController.java +++ b/src/main/java/nlib/col/web/ReadController.java @@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestBody; @@ -67,6 +68,7 @@ public class ReadController extends NlibCommonController { * @return * @throws Exception */ + @Secured("ROLE_USER") @RequestMapping(value={"/read/confirmReadFromCart.do", "/read/confirmRead.do"}) public String confirmRent(HttpServletRequest request, CollectionVO readVO, ModelMap model) throws Exception { @@ -107,6 +109,7 @@ public class ReadController extends NlibCommonController { * @return * @throws Exception */ + @Secured("ROLE_USER") @RequestMapping(value={"/read/insertReadItemsFromCart.do", "/read/insertReadItems.do"}) public String insertReadItems(HttpServletRequest request, CollectionVO readVO, ModelMap model) throws Exception { @@ -170,6 +173,7 @@ public class ReadController extends NlibCommonController { * @return * @throws Exception */ + @Secured("ROLE_USER") @RequestMapping("/read/listReadItems.do") public String listReadItems(HttpServletRequest request, CollectionVO searchVO, ModelMap model, String message) throws Exception { @@ -199,8 +203,9 @@ public class ReadController extends NlibCommonController { * @param req * @return */ + @Secured("ROLE_USER") @RequestMapping(value="/read/listReadItemsAjax.do") - public ResponseEntity listRentItemsAjax( + public ResponseEntity listReadItemsAjax( HttpServletRequest request, @RequestBody CollectionVO searchVO) { @@ -253,8 +258,9 @@ public class ReadController extends NlibCommonController { return makeResponseEntityJson(retMap); } + @Secured("ROLE_USER") @RequestMapping(value="/read/cancelReadItemAjax.do") - public ResponseEntity cancelRentItemAjax( + public ResponseEntity cancelReadItemAjax ( HttpServletRequest request, @RequestBody CollectionVO searchVO) { diff --git a/src/main/java/nlib/col/web/RentController.java b/src/main/java/nlib/col/web/RentController.java index a48d18b8..d3df1e78 100644 --- a/src/main/java/nlib/col/web/RentController.java +++ b/src/main/java/nlib/col/web/RentController.java @@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; @@ -81,6 +82,7 @@ public class RentController extends NlibCommonController * @return * @throws Exception */ + @Secured("ROLE_USER") @RequestMapping("/rent/listRentItems.do") public String listRentItems(HttpServletRequest request, CollectionVO searchVO, ModelMap model, String message) throws Exception { @@ -110,6 +112,7 @@ public class RentController extends NlibCommonController * @param req * @return */ + @Secured("ROLE_USER") @RequestMapping(value="/rent/listRentItemsAjax.do") public ResponseEntity listRentItemsAjax( HttpServletRequest request, @@ -164,7 +167,7 @@ public class RentController extends NlibCommonController return makeResponseEntityJson(retMap); } - + @Secured("ROLE_USER") @RequestMapping(value="/rent/cancelRentItemAjax.do") public ResponseEntity cancelRentItemAjax( HttpServletRequest request, @@ -213,6 +216,7 @@ public class RentController extends NlibCommonController return makeResponseEntityJson(retMap); } + @Secured("ROLE_USER") @RequestMapping(value={"/rent/confirmRentFromCart.do", "/rent/confirmRent.do"}) public String confirmRent(HttpServletRequest request, CollectionVO rentVO, ModelMap model) throws Exception { @@ -241,6 +245,7 @@ public class RentController extends NlibCommonController return "nlib/rent/confirmRent"; } + @Secured("ROLE_USER") @RequestMapping(value={"/rent/insertRentItemsFromCart.do", "/rent/insertRentItems.do"}) public String insertRentItems(HttpServletRequest request, CollectionVO rentVO, ModelMap model) throws Exception { @@ -277,305 +282,4 @@ public class RentController extends NlibCommonController return retJsp; } - -// -// -// /** 대출 목록 화면을 호출한다. -// * @param req -// * @return -// */ -// @RequestMapping("/rent/listCanceledRentItems.do") -// public String listCanceledRentItems(HttpServletRequest req, Authentication authentication, @RequestParam Map paramMap, ModelMap model) throws Exception { -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// // 페이징 사이즈 코드 목록 조회 (DB방식으로 변경 2021.08.06 KNKIM) -// List> pageSizeCodes = codeService.listCodes("PAGE_SIZE_OPTION"); -// -// // 반환 정보 -// model.addAttribute("pageIndex" , pageIndex); -// model.addAttribute("pageSize" , pageSize); -// model.addAttribute("searchKeyword", searchKeyword); -// model.addAttribute("pageSizeCodes", pageSizeCodes); -// return "nlib/rent/listCanceledRentItems"; -// } -// -// /** -// * 대출 취소 목록을 조회한다. -// * -// * @param req -// * @return -// */ -// @RequestMapping(value="/rent/listCanceledRentItemsAjax.do") -// public ResponseEntity listCanceledRentItemsAjax(HttpServletRequest req, -// Authentication authentication, @RequestBody Map paramMap) { -// -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// //------------------------------- -// // REQ VO 구성 -// //------------------------------- -// DataApiReqVO reqVO = new DataApiReqVO(); -// reqVO.setPageIndex(pageIndex); -// reqVO.setPageSize(pageSize); -// reqVO.putInfoItem("searchKeyword", searchKeyword); -// -// // 요청 -// DataApiResVO resVO = rentService.listCanceledRentItems(reqVO); -// -// //------------------------------- -// // JSON변환 응답 처리 -// //------------------------------- -// // JS-GRID 페이징 처리를 포함한 응답값 처리 -// // {data: [{...}], -// // itemsCount: 255 -// // } -// HashMap retMap = new HashMap(); -// retMap.put("data", resVO.getList(DataApiVO.XML_EL_NAME_RECORD)); -// retMap.put("itemsCount", resVO.getRecordTotCount()); -// -// return makeResponseEntityJson(retMap); -// } -// -// /** 반납 연기 화면을 호출한다. -// * @param req -// * @return -// */ -// @RequestMapping("/rent/listPostpones.do") -// public String listPostpones(HttpServletRequest req, Authentication authentication, @RequestParam Map paramMap, ModelMap model) throws Exception { -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// // 페이징 사이즈 코드 목록 조회 (DB방식으로 변경 2021.08.06 KNKIM) -// List> pageSizeCodes = codeService.listCodes("PAGE_SIZE_OPTION"); -// -// // 반환 정보 -// model.addAttribute("pageIndex" , pageIndex); -// model.addAttribute("pageSize" , pageSize); -// model.addAttribute("searchKeyword", searchKeyword); -// model.addAttribute("pageSizeCodes", pageSizeCodes); -// return "nlib/rent/listPostpones"; -// } -// -// /** -// * 반납 연기 목록을 조회한다. -// * -// * @param req -// * @return -// */ -// @RequestMapping(value="/rent/listPostponesAjax.do") -// public ResponseEntity listPostponesAjax(HttpServletRequest req, -// Authentication authentication, @RequestBody Map paramMap) { -// -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// //------------------------------- -// // REQ VO 구성 -// //------------------------------- -// DataApiReqVO reqVO = new DataApiReqVO(); -// reqVO.setPageIndex(pageIndex); -// reqVO.setPageSize(pageSize); -// reqVO.putInfoItem("searchKeyword", searchKeyword); -// -// // 요청 -// DataApiResVO resVO = rentService.listPostpones(reqVO); -// -// //------------------------------- -// // JSON변환 응답 처리 -// //------------------------------- -// // JS-GRID 페이징 처리를 포함한 응답값 처리 -// // {data: [{...}], -// // itemsCount: 255 -// // } -// HashMap retMap = new HashMap(); -// retMap.put("data", resVO.getList(DataApiVO.XML_EL_NAME_RECORD)); -// retMap.put("itemsCount", resVO.getRecordTotCount()); -// -// return makeResponseEntityJson(retMap); -// } -// -// public ModelMap listCanceledRentItems(HttpServletRequest req) { -// return null; -// } -// -// /** 대출 예약 화면을 호출한다. -// * @param req -// * @return -// */ -// @RequestMapping("/rent/listReservations.do") -// public String listReservations(HttpServletRequest req, Authentication authentication, @RequestParam Map paramMap, ModelMap model) throws Exception { -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// // 페이징 사이즈 코드 목록 조회 (DB방식으로 변경 2021.08.06 KNKIM) -// List> pageSizeCodes = codeService.listCodes("PAGE_SIZE_OPTION"); -// -// // 반환 정보 -// model.addAttribute("pageIndex" , pageIndex); -// model.addAttribute("pageSize" , pageSize); -// model.addAttribute("searchKeyword", searchKeyword); -// model.addAttribute("pageSizeCodes", pageSizeCodes); -// return "nlib/rent/listReservations"; -// } -// -// /** -// * 대출 예약 목록을 조회한다. -// * -// * @param req -// * @return -// */ -// @RequestMapping(value="/rent/listReservationsAjax.do") -// public ResponseEntity listReservationsAjax(HttpServletRequest req, -// Authentication authentication, @RequestBody Map paramMap) { -// -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// //------------------------------- -// // REQ VO 구성 -// //------------------------------- -// DataApiReqVO reqVO = new DataApiReqVO(); -// reqVO.setPageIndex(pageIndex); -// reqVO.setPageSize(pageSize); -// reqVO.putInfoItem("searchKeyword", searchKeyword); -// -// // 요청 -// DataApiResVO resVO = rentService.listReservations(reqVO); -// -// //------------------------------- -// // JSON변환 응답 처리 -// //------------------------------- -// // JS-GRID 페이징 처리를 포함한 응답값 처리 -// // {data: [{...}], -// // itemsCount: 255 -// // } -// HashMap retMap = new HashMap(); -// retMap.put("data", resVO.getList(DataApiVO.XML_EL_NAME_RECORD)); -// retMap.put("itemsCount", resVO.getRecordTotCount()); -// -// return makeResponseEntityJson(retMap); -// } -// -// public ModelMap cancelReservations(HttpServletRequest req) { -// return null; -// } -// -// /** -// * 열람 요청 화면을 호출한다. -// * -// * @param req -// * @return -// */ -// @RequestMapping("/rent/listRequestsForViewingItem.do") -// public String listRequestsForViewingItem(HttpServletRequest req, Authentication authentication, @RequestParam Map paramMap, ModelMap model) throws Exception { -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// // 페이징 사이즈 코드 목록 조회 (DB방식으로 변경 2021.08.06 KNKIM) -// List> pageSizeCodes = codeService.listCodes("PAGE_SIZE_OPTION"); -// -// // 반환 정보 -// model.addAttribute("pageIndex" , pageIndex); -// model.addAttribute("pageSize" , pageSize); -// model.addAttribute("searchKeyword", searchKeyword); -// model.addAttribute("pageSizeCodes", pageSizeCodes); -// return "nlib/rent/listRequestsForViewingItem"; -// } -// -// /** -// * 열람 요청 목록을 조회한다. -// * -// * @param req -// * @return -// */ -// @RequestMapping(value="/rent/listRequestsForViewingItemAjax.do") -// public ResponseEntity listRequestsForViewingItemAjax(HttpServletRequest req, -// Authentication authentication, @RequestBody Map paramMap) { -// -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = StringUtil.getString(paramMap.get("pageIndex"), "1"); -// String pageSize = StringUtil.getString(paramMap.get("pageSize") , DEFUALT_PAGE_SIZE); -// -// //------------------------------- -// // REQ VO 구성 -// //------------------------------- -// DataApiReqVO reqVO = new DataApiReqVO(); -// reqVO.setPageIndex(pageIndex); -// reqVO.setPageSize(pageSize); -// reqVO.putInfoItem("searchKeyword", searchKeyword); -// -// // 요청 -// DataApiResVO resVO = rentService.listRequestsForViewingItem(reqVO); -// -// //------------------------------- -// // JSON변환 응답 처리 -// //------------------------------- -// // JS-GRID 페이징 처리를 포함한 응답값 처리 -// // {data: [{...}], -// // itemsCount: 255 -// // } -// HashMap retMap = new HashMap(); -// retMap.put("data", resVO.getList(DataApiVO.XML_EL_NAME_RECORD)); -// retMap.put("itemsCount", resVO.getRecordTotCount()); -// -// return makeResponseEntityJson(retMap); -// } -// -// /** -// * 묻고답하기 상세 내용 조회한다. -// * -// * @param req -// * @return -// */ -// @RequestMapping("/rent/selectRequestInfoForViewingItem.do") -// public String selectRequestInfoForViewingItem(HttpServletRequest req, Authentication authentication, @RequestParam Map paramMap, ModelMap model) { -// -// // 목록 이동시 전달할 매개변수 -// String searchKeyword = paramMap.get("searchKeyword"); -// String pageIndex = paramMap.get("pageIndex"); -// String pageSize = paramMap.get("pageSize"); -// String message = paramMap.get("message"); -// -// // 게시물 번호 -// String articleNo = paramMap.get("articleNo"); -// -// log.debug("selectRequestInfoForViewingItem > pageIndex = " + pageIndex); -// log.debug("selectRequestInfoForViewingItem > pageSize = " + pageSize); -// log.debug("selectRequestInfoForViewingItem > searchKeyword = " + searchKeyword); -// log.debug("selectRequestInfoForViewingItem > articleNo = " + articleNo); -// log.debug("selectRequestInfoForViewingItem > message = " + message); -// -// //------------------------------- -// // REQ VO 구성 -// //------------------------------- -// DataApiReqVO reqVO = new DataApiReqVO(); -// reqVO.setPageIndex(pageIndex); -// reqVO.setPageSize(pageSize); -// reqVO.putInfoItem("boardNo", "QNA"); // 게시판ID -// reqVO.putInfoItem("articleNo", articleNo); // 게시물번호 -// -// // 요청 -// DataApiResVO resVO = rentService.selectRequestInfoForViewingItem(reqVO); -// -// // 반환 정보 -// model.addAttribute("articleNo" , articleNo); -// model.addAttribute("article" , resVO.getInfo()); // 게시물 상세 -// model.addAttribute("preArticle" , resVO.getList(DataApiVO.XML_EL_NAME_RECORD).get(0)); // 이전글 정보 -// model.addAttribute("nextArticle" , resVO.getList(DataApiVO.XML_EL_NAME_RECORD).get(1)); // 다음글 정보 -// model.addAttribute("message" , message); -// model.addAttribute("pageIndex" , pageIndex); -// model.addAttribute("pageSize" , pageSize); -// model.addAttribute("searchKeyword", searchKeyword); -// -// return "nlib/rent/selectRequestInfoForViewingItem"; -// } } \ No newline at end of file diff --git a/src/main/java/nlib/security/CustomRequestCache.java b/src/main/java/nlib/security/CustomRequestCache.java new file mode 100644 index 00000000..64ec938f --- /dev/null +++ b/src/main/java/nlib/security/CustomRequestCache.java @@ -0,0 +1,38 @@ +package nlib.security; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; + +/** + *
+ * @Class Name : CustomRequestCache.java
+ * 
+ * @Description : 스프링 시큐리티에 권한 실패시 HttpSessionRequestCache에 저장되는 정보 커스터마이징 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 11. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 11. 16. + * @version 1.0 + * + */ +public class CustomRequestCache extends HttpSessionRequestCache { + + @Override + public void saveRequest(HttpServletRequest request, HttpServletResponse response) { + + // Ajax Reqeust 들도 캐쉬되도록 처리함 + super.saveRequest(request, response); + } +} \ No newline at end of file diff --git a/src/main/java/nlib/security/SpringSecurityConfig.java b/src/main/java/nlib/security/SpringSecurityConfig.java index 50cfa776..d0d89782 100644 --- a/src/main/java/nlib/security/SpringSecurityConfig.java +++ b/src/main/java/nlib/security/SpringSecurityConfig.java @@ -70,6 +70,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/**").permitAll() + .and().requestCache().requestCache(new CustomRequestCache()) .and().formLogin() .loginPage(NlibProperty.getString("login.url") + "?login=req") .permitAll() diff --git a/src/main/java/nlib/user/web/LoginController.java b/src/main/java/nlib/user/web/LoginController.java index 4e70544e..6656e0f5 100644 --- a/src/main/java/nlib/user/web/LoginController.java +++ b/src/main/java/nlib/user/web/LoginController.java @@ -12,6 +12,9 @@ import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.SavedRequest; @@ -23,6 +26,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import com.fasterxml.jackson.databind.ObjectMapper; + import egovframework.com.ext.oauth.service.OAuthConfig; import egovframework.com.ext.oauth.service.OAuthLogin; import egovframework.com.ext.oauth.service.OAuthUniversalUser; @@ -113,7 +118,11 @@ public class LoginController extends NlibCommonController { RequestCache cache = new HttpSessionRequestCache(); SavedRequest savedRequest = cache.getRequest(req, res); if (savedRequest != null) { - councilReturnUrl = savedRequest.getRedirectUrl(); + if(savedRequest.getRedirectUrl().contains("Ajax.do")) { + cache.removeRequest(req, res); + } else { + councilReturnUrl = savedRequest.getRedirectUrl(); + } log.debug("setCouncilInfo > HttpSessionRequestCache에서 획득 councilReturnUrl = " + councilReturnUrl); } @@ -210,6 +219,23 @@ public class LoginController extends NlibCommonController { return "redirect:" + redirect; } + /** + * Ajax 요청에 대한 권한 부재시 오류 처리 + * + * @param req + * @param res + * @return + * @throws Exception + */ + @RequestMapping(value= {"/login/responseDeniedAuth.do"}) + public ResponseEntity responseDeniedAuth(HttpServletRequest req, HttpServletResponse res) throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + String errorStr = "로그인 후, 이용해 주시기 바랍니다."; + log.debug("responseDeniedAuth > errorStr=" + errorStr); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body(errorStr); + } + /** * 로그인 정보 입력 화면을 출력한다. * @@ -233,6 +259,16 @@ public class LoginController extends NlibCommonController { Model model) throws Exception { String reqPath = req.getServletPath(); + + // Ajax 호출이면서 인증 오류에 따른 요청인 경우, Ajax용 RES 생성 함수로 전환 + if("req".equals(login)) { + RequestCache cache = new HttpSessionRequestCache(); + SavedRequest savedRequest = cache.getRequest(req, res); + if (savedRequest != null && savedRequest.getRedirectUrl().contains("Ajax.do")) { + cache.removeRequest(req, res); + return "redirect:/login/responseDeniedAuth.do"; + } + } // callType if(StringUtil.isEmpty(callType)) { diff --git a/src/main/webapp/WEB-INF/jsp/nlib/cmm/listNotifications.jsp b/src/main/webapp/WEB-INF/jsp/nlib/cmm/listNotifications.jsp index 4f92a559..bb8d782f 100644 --- a/src/main/webapp/WEB-INF/jsp/nlib/cmm/listNotifications.jsp +++ b/src/main/webapp/WEB-INF/jsp/nlib/cmm/listNotifications.jsp @@ -167,8 +167,8 @@ $( document ).ready(function() { pageLoad("fn_searchArticle", jsonObj.pagingPageIndex, jsonObj.pagingTotRecordCount, jsonObj.pagingStartPage, jsonObj.pagingEndPage, jsonObj.pagingLastPage); - }).fail(function (jqXHR, textStatus, errorThrown) { - alert("조회에 실패하였습니다. 관리자에게 문의 바랍니다."); + }).fail(function (request, textStatus, errorThrown) { + alert("조회에 실패하였습니다. \n" + gfn_removeQuotes(request.responseText)); }); } @@ -196,6 +196,7 @@ $( document ).ready(function() { 0

- 최근 한달동안 발송된 알림 내역만 보관됩니다.

+