diff --git a/egovframe-template-simple-react-contribution/src/pages/admin/users/UserInfoModal.jsx b/egovframe-template-simple-react-contribution/src/pages/admin/users/UserInfoModal.jsx index d660a88..2d54780 100644 --- a/egovframe-template-simple-react-contribution/src/pages/admin/users/UserInfoModal.jsx +++ b/egovframe-template-simple-react-contribution/src/pages/admin/users/UserInfoModal.jsx @@ -67,7 +67,7 @@ function UserInfoModal({savedInfo, reloadFunction}){ } }, (resp) => { - debugger + } ) } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/entity/ThLoginLog.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/entity/ThLoginLog.java new file mode 100644 index 0000000..cfbe5c9 --- /dev/null +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/entity/ThLoginLog.java @@ -0,0 +1,44 @@ +package com.dbnt.kcscbackend.admin.logs.entity; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.*; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Getter +@Setter +@Accessors(chain = true) +@Entity +@NoArgsConstructor +@DynamicInsert +@DynamicUpdate +@Table(name = "th_login_log") +public class ThLoginLog { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ll_seq") + private Long llSeq; + + @Column(name = "user_id") + private String userId; + + @Column(name = "access_dt") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime accessDt; + + @Column(name = "ip_address") + private String ipAddress; + + @Column(name = "session_id") + private String sessionId; + + @Column(name = "access_type") + private String accessType; +} diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/entity/TnDailyUserConnLog.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/entity/TnDailyUserConnLog.java index 9ae62a7..782ea01 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/entity/TnDailyUserConnLog.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/entity/TnDailyUserConnLog.java @@ -10,7 +10,6 @@ import org.springframework.format.annotation.DateTimeFormat; import javax.persistence.*; import java.time.LocalDate; -import java.awt.*; @Getter @Setter @@ -22,13 +21,20 @@ import java.awt.*; @Table(name = "tn_daily_user_log") public class TnDailyUserConnLog { @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "dul_seq") private Long dulSeq; - @Column(name = "log_cnt") - private Long logCnt; - @Column(name = "log_dt") @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate logDt; + + @Column(name = "log_cnt") + private Long logCnt; + + @Column(name = "mobile_cnt") + private Long mobileCnt; + + @Column(name = "pc_cnt") + private Long pcCnt; } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/PrivacyLogsRepository.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/PrivacyLogsRepository.java index ad0fe00..df86bd4 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/PrivacyLogsRepository.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/PrivacyLogsRepository.java @@ -5,6 +5,6 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; -public interface PrivacyLogsRepository extends JpaRepository { +public interface PrivacyLogsRepository extends JpaRepository { List findAllByOrderByUplSeqDesc(); } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/ThLoginLogRepository.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/ThLoginLogRepository.java new file mode 100644 index 0000000..f79973b --- /dev/null +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/ThLoginLogRepository.java @@ -0,0 +1,12 @@ +package com.dbnt.kcscbackend.admin.logs.repository; + +import com.dbnt.kcscbackend.admin.logs.entity.ThLoginLog; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.time.LocalDateTime; +import java.util.List; + +public interface ThLoginLogRepository extends JpaRepository { + + List findByUserIdAndAccessDtAfter(String userId, LocalDateTime accessDt); +} diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/UserLogsRepository.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/UserLogsRepository.java index 8c8d67e..07c6059 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/UserLogsRepository.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/repository/UserLogsRepository.java @@ -5,7 +5,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.time.LocalDate; import java.util.List; +import java.util.Optional; public interface UserLogsRepository extends JpaRepository { @@ -21,5 +23,5 @@ public interface UserLogsRepository extends JpaRepository selectCountUser(@Param("startDate") String startDate, @Param("endDate") String endDate); - + Optional findByLogDt(LocalDate logDt); } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/service/AdminLogsService.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/service/AdminLogsService.java index 8059cf6..12ce23c 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/service/AdminLogsService.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/logs/service/AdminLogsService.java @@ -1,13 +1,18 @@ package com.dbnt.kcscbackend.admin.logs.service; +import com.dbnt.kcscbackend.admin.logs.entity.ThLoginLog; import com.dbnt.kcscbackend.admin.logs.entity.ThPrivacyLog; +import com.dbnt.kcscbackend.admin.logs.entity.TnDailyUserConnLog; import com.dbnt.kcscbackend.admin.logs.repository.PrivacyLogsRepository; +import com.dbnt.kcscbackend.admin.logs.repository.ThLoginLogRepository; +import com.dbnt.kcscbackend.admin.logs.repository.UserLogsRepository; import lombok.RequiredArgsConstructor; import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,6 +22,8 @@ import java.util.Map; public class AdminLogsService extends EgovAbstractServiceImpl { private final PrivacyLogsRepository privacyLogsRepository; + private final ThLoginLogRepository loginLogRepository; + private final UserLogsRepository userLogsRepository; public Map selectPrivacyList() { Map resultMap = new HashMap<>(); @@ -46,4 +53,44 @@ public class AdminLogsService extends EgovAbstractServiceImpl { log.setTargetUserId(targetUserId); privacyLogsRepository.save(log); } + + @Transactional + public void insertLoginLog(String userId, String ipAddress, String accessToken, String accessType, String webType){ + ThLoginLog loginLog = new ThLoginLog(); + loginLog.setUserId(userId); + loginLog.setIpAddress(ipAddress); + loginLog.setSessionId(accessToken); + loginLog.setAccessType(accessType); + loginLog.setAccessDt(LocalDateTime.now()); + loginLogRepository.save(loginLog); + + // 로그인 기록이면 tn_daily_yser_log 카운트 조정 + if(accessType.equals("Y")){ + //오늘 일자 로그 조회 + TnDailyUserConnLog userConnLog = userLogsRepository.findByLogDt(LocalDate.now()).orElse(null); + if(userConnLog==null){ + userConnLog = new TnDailyUserConnLog(); + userConnLog.setLogDt(LocalDate.now()); + userConnLog.setLogCnt(0L); + userConnLog.setMobileCnt(0L); + userConnLog.setPcCnt(0L); + } + if(webType.equals("PC")){ + userConnLog.setPcCnt(userConnLog.getPcCnt()+1); + }else{ + userConnLog.setMobileCnt(userConnLog.getMobileCnt()+1); + } + //같은 일자 로그인 기록 확인 + LocalDateTime now = LocalDateTime.now(); + now = now.minusHours(now.getHour()); + now = now.minusMinutes(now.getMinute()); + now = now.minusSeconds(now.getSecond()); + List todayLoginLog = loginLogRepository.findByUserIdAndAccessDtAfter(userId, now); + if(todayLoginLog.size()==0){ + userConnLog.setLogCnt(userConnLog.getLogCnt()+1); + } + userLogsRepository.save(userConnLog); + + } + } } 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 04d3650..cab4612 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 @@ -1,5 +1,6 @@ package com.dbnt.kcscbackend.config.security; +import com.dbnt.kcscbackend.admin.logs.service.AdminLogsService; import com.dbnt.kcscbackend.auth.entity.UserInfo; import com.dbnt.kcscbackend.config.common.ResponseCode; import com.dbnt.kcscbackend.config.egov.EgovProperties; @@ -31,6 +32,7 @@ import java.util.List; public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { private final EgovJwtTokenUtil jwtTokenUtil; + private final AdminLogsService adminLogsService; private RequestCache requestCache = new HttpSessionRequestCache(); private static final List adminIpList = Arrays.asList(EgovProperties.getProperty("Globals.admin.allow-ip").split(",")); @@ -53,12 +55,14 @@ public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticati securityUser = (UserInfo) principal; } } + String accessIp = ClientUtils.getRemoteIP(request); + // application/json(ajax) 요청일 경우 아래의 처리! MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); MediaType jsonMimeType = MediaType.APPLICATION_JSON; HashMap resultMap = new HashMap<>(); - - /*if(securityUser.getUserId().equals("admin") && !adminIpList.contains(ClientUtils.getRemoteIP(request))){ + + /*if(securityUser.getUserId().equals("admin") && !adminIpList.contains(accessIp)){ resultMap.put("resultCode", ResponseCode.FAILED.getCode()); resultMap.put("resultMessage", "관리자 계정은 지정된 아이피에서만 접속할 수 있습니다.\n필요한 경우 관리자에게 요청하십시오.\n접속자 아이피: "+ClientUtils.getRemoteIP(request)); }else{ @@ -78,6 +82,9 @@ public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticati resultMap.put("accessToken", accessToken); resultMap.put("refreshToken", refreshToken); + //로그인 로그 기록 + adminLogsService.insertLoginLog(securityUser.getUserId(), accessIp, accessToken, "Y", ClientUtils.getWebType(request)); + 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 6c81b8a..5362900 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 @@ -1,5 +1,6 @@ package com.dbnt.kcscbackend.config.security; +import com.dbnt.kcscbackend.admin.logs.service.AdminLogsService; import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil; import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationEntryPoint; import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationFilter; @@ -49,6 +50,7 @@ public class SecurityConfig { private UserDetailsService loginService; private final ObjectMapper objectMapper; private final EgovJwtTokenUtil egovJwtTokenUtil; + private final AdminLogsService adminLogsService; //Http Methpd : Get 인증예외 List private String[] AUTH_GET_WHITELIST = { @@ -145,7 +147,7 @@ public class SecurityConfig { @Bean public JsonAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() { - JsonAuthenticationFilter jsonAuthenticationFilter = new JsonAuthenticationFilter(objectMapper, new CustomUrlAuthenticationSuccessHandler(egovJwtTokenUtil), loginFailureHandler()); + JsonAuthenticationFilter jsonAuthenticationFilter = new JsonAuthenticationFilter(objectMapper, new CustomUrlAuthenticationSuccessHandler(egovJwtTokenUtil, adminLogsService), loginFailureHandler()); jsonAuthenticationFilter.setAuthenticationManager(authenticationManager()); return jsonAuthenticationFilter; } diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/util/ClientUtils.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/util/ClientUtils.java index 0581e9f..ee2a028 100644 --- a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/util/ClientUtils.java +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/config/util/ClientUtils.java @@ -29,4 +29,20 @@ public class ClientUtils { return ip; } + + public static String getWebType(HttpServletRequest request) { + String filter = "iphone|ipod|android|windows ce|blackberry|symbian|windows phone|webos|opera mini|opera mobi|polaris|iemobile|lgtelecom|nokia|sonyericsson|lg|samsung"; + String filters[] = filter.split("\\|"); + String webType = ""; + + for(String tmp : filters){ + if (request.getHeader("User-Agent").toLowerCase().contains(tmp)) { + webType = "MOBILE"; + break; + } else { + webType = "PC"; + } + } + return webType; + } }