diff --git a/src/main/java/nlib/security/SecUserDAO.java b/src/main/java/nlib/security/SecUserDAO.java index 9d56c79c..df4f908a 100644 --- a/src/main/java/nlib/security/SecUserDAO.java +++ b/src/main/java/nlib/security/SecUserDAO.java @@ -7,9 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; -import egovframework.rte.psl.dataaccess.EgovAbstractMapper; -import nlib.restful.service.DataApiReqVO; -import nlib.restful.service.DataApiResVO; +import egovframework.com.cmm.service.impl.EgovComAbstractDAO; import nlib.util.StringUtil; /** @@ -36,30 +34,30 @@ import nlib.util.StringUtil; * */ @Repository("secUserDAO") -public class SecUserDAO extends EgovAbstractMapper { +public class SecUserDAO extends EgovComAbstractDAO { private static final Logger log = LoggerFactory.getLogger(SecUserDAO.class); - public SecUserVO loadUserByUsername(String userName) { + public SecUserVO loadUserByUsername(String loginUserId) { - HashMap info = selectOne("secUserDAO.loadUserByUsername", userName); + SecUserVO uInfo = (SecUserVO)selectOne("SecUserDAO.loadUserByUsername", loginUserId); - // 사용자 정보 담기 - SecUserVO ret = new SecUserVO(); - ret.setUserId ((String)info.get("userId")); - ret.setUserNm ((String)info.get("userName")); - ret.setUserPwd ((String)info.get("userPwd")); - ret.setLoginUserId ((String)info.get("loginUserId")); - - // 다중 권한 설정 - String authorities = (String)info.get("authorities"); - if(StringUtil.isEmpty(authorities)) ret.addAuthority(SecUserVO.DEFAULT_ROLE); - else { - String[] authArr = authorities.split(","); - Arrays.stream(authArr).forEach(auth -> ret.addAuthority(auth)); + if(uInfo == null) { + uInfo = new SecUserVO(); + } else { + // 다중 권한 설정 + String authorities = (String)uInfo.getAuthorityList(); + if(StringUtil.isEmpty(authorities)) { + uInfo.addAuthority(SecUserVO.DEFAULT_ROLE); + } else { + String[] authArr = authorities.split(","); + for(String auth : authArr) { + uInfo.addAuthority(auth); + } + } } - return ret; + return uInfo; } } diff --git a/src/main/java/nlib/security/SecUserDetailsService.java b/src/main/java/nlib/security/SecUserDetailsService.java index 52718168..a697dedb 100644 --- a/src/main/java/nlib/security/SecUserDetailsService.java +++ b/src/main/java/nlib/security/SecUserDetailsService.java @@ -52,12 +52,12 @@ public class SecUserDetailsService implements UserDetailsService { * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) */ @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + public UserDetails loadUserByUsername(String loginUserId) throws UsernameNotFoundException { - SecUserVO secUserVO = secUserDAO.loadUserByUsername(username); + SecUserVO secUserVO = secUserDAO.loadUserByUsername(loginUserId); if(secUserVO == null) { - throw new UsernameNotFoundException(username); + throw new UsernameNotFoundException(loginUserId); } return secUserVO; } diff --git a/src/main/java/nlib/security/SecUserVO.java b/src/main/java/nlib/security/SecUserVO.java index 25783ee0..45782787 100644 --- a/src/main/java/nlib/security/SecUserVO.java +++ b/src/main/java/nlib/security/SecUserVO.java @@ -7,6 +7,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; +import nlib.cmm.service.NlibProperty; import nlib.user.service.NlibLoginVO; /** @@ -35,8 +36,12 @@ public class SecUserVO extends NlibLoginVO implements UserDetails { private static final long serialVersionUID = -8274004534207618048L; - public static final String ROLE_USER = "ROLE_USER"; - public static final String ROLE_ADMIN = "ROLE_ADMIN"; + /* 권한 ROLE 명칭 */ + public static final String ROLE_USER = NlibProperty.getString("auth.role.user"); // 일반사용자 + public static final String ROLE_ADMIN = NlibProperty.getString("auth.role.admin"); // 관리자 + public static final String ROLE_SYSTEM = NlibProperty.getString("auth.role.system"); // 시스템관리자 + + /* 기본권한 ROLE */ public static final String DEFAULT_ROLE = ROLE_USER; ArrayList auth = null; /* 권한 목록 */ diff --git a/src/main/java/nlib/user/service/LoginService.java b/src/main/java/nlib/user/service/LoginService.java index 836d34a0..87c5f80a 100644 --- a/src/main/java/nlib/user/service/LoginService.java +++ b/src/main/java/nlib/user/service/LoginService.java @@ -10,7 +10,7 @@ public interface LoginService { public String login(HttpServletRequest req, String username, String password); - public String loginOauth(String snsUid); + public String loginOauth(HttpServletRequest req, String snsUserId); public DataApiResVO logout(DataApiReqVO reqVO); diff --git a/src/main/java/nlib/user/service/NlibLoginVO.java b/src/main/java/nlib/user/service/NlibLoginVO.java index ef21e154..6b2f065c 100644 --- a/src/main/java/nlib/user/service/NlibLoginVO.java +++ b/src/main/java/nlib/user/service/NlibLoginVO.java @@ -35,6 +35,7 @@ public class NlibLoginVO implements Serializable { private String userId; /* 사용자아이디 (ex: U1000000001) */ private String loginUserId; /* 로그인사용자ID (이메일주소) */ private String deptSeq; /* 조직코드 */ + private String deptNm; /* 조직명 */ private String userDiv; /* 사용자구분 */ private String userNm; /* 사용자명 */ private String userPwd; /* 비밀번호 */ @@ -69,7 +70,9 @@ public class NlibLoginVO implements Serializable { private String gender; /* 성별(M:남자,F:여자) */ private String authKey; /* 로그인 인증키 */ - + private String loginSucsYn; /* 로그인성공여부 */ + private String accIp; /* 접속IP */ + private String authorityList; /* 권한ROLE 리스트 */ /** * 로그인인증키값을 리턴한다. 만일 존재하지 않을 경우, userId를 기반으로 인증키를 생성하여 리턴한다. @@ -378,5 +381,37 @@ public class NlibLoginVO implements Serializable { public void setGender(String gender) { this.gender = gender; } + + public String getDeptNm() { + return deptNm; + } + + public void setDeptNm(String deptNm) { + this.deptNm = deptNm; + } + + public String getAccIp() { + return accIp; + } + + public void setAccIp(String accIp) { + this.accIp = accIp; + } + + public String getLoginSucsYn() { + return loginSucsYn; + } + + public void setLoginSucsYn(String loginSucsYn) { + this.loginSucsYn = loginSucsYn; + } + + public String getAuthorityList() { + return authorityList; + } + + public void setAuthorityList(String authorityList) { + this.authorityList = authorityList; + } } diff --git a/src/main/java/nlib/user/service/impl/LoginDAO.java b/src/main/java/nlib/user/service/impl/LoginDAO.java index ba8f2b21..86a1d1de 100644 --- a/src/main/java/nlib/user/service/impl/LoginDAO.java +++ b/src/main/java/nlib/user/service/impl/LoginDAO.java @@ -3,12 +3,14 @@ package nlib.user.service.impl; import org.springframework.stereotype.Repository; +import egovframework.com.cmm.service.impl.EgovComAbstractDAO; import nlib.restful.service.DataApiReqVO; import nlib.restful.service.DataApiResVO; +import nlib.user.service.NlibLoginVO; @Repository("loginDAO") -public class LoginDAO -{ +public class LoginDAO extends EgovComAbstractDAO { + public DataApiResVO login(DataApiReqVO reqVO) { return null; } @@ -17,5 +19,12 @@ public class LoginDAO return null; } - + public NlibLoginVO selectLoginUserInfo(String snsUserId) { + return (NlibLoginVO) selectOne("LoginDAO.selectLoginUserInfo", snsUserId); + } + + public void insertLoginLog(NlibLoginVO userVO) { + insert("BBSArticle.insertLoginLog", userVO); + } + } \ No newline at end of file diff --git a/src/main/java/nlib/user/service/impl/LoginServiceImpl.java b/src/main/java/nlib/user/service/impl/LoginServiceImpl.java index b37375cf..5e6b70fe 100644 --- a/src/main/java/nlib/user/service/impl/LoginServiceImpl.java +++ b/src/main/java/nlib/user/service/impl/LoginServiceImpl.java @@ -20,6 +20,7 @@ import nlib.restful.service.DataApiReqVO; import nlib.restful.service.DataApiResVO; import nlib.security.SecUserVO; import nlib.user.service.LoginService; +import nlib.user.service.NlibLoginVO; import nlib.util.StringUtil; @Service("loginService") @@ -72,40 +73,51 @@ public class LoginServiceImpl implements LoginService } - /* - * SNS 연동을 통한 로그인 처리를 수행한다. + /* SNS 연동 SSO를 통한 로그인 처리한다. + * + * return값이 null인 경우, 정상적인 로그인 처리 완료 + * null이 아닌 경우, REDIRECT되어야 하는 URL(오류 코드 포함) * */ - public String loginOauth(String snsUid) { + public String loginOauth(HttpServletRequest req, String snsUserId) { // SNS 연동 사용자UID로 사용자정보 조회 - if(StringUtil.isEmpty(snsUid)) return null; + if(StringUtil.isEmpty(snsUserId)) return "/login/loginForm.do?error=req-sns-sso"; + + NlibLoginVO nLoginVO = loginDAO.selectLoginUserInfo(snsUserId); + + if(nLoginVO == null) { + return "/login/loginForm.do?error=new-membership"; + } -// // 아이디와 패스워드로, Security 가 알아 볼 수 있는 token 객체로 변경한다. -// UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); -// -// try { -// // AuthenticationManager 에 token 을 넘기면 UserDetailsService 가 받아 처리하도록 한다. -// Authentication authentication = authenticationManager.authenticate(token); -// -// // AuthKey 등록 -// SecUserVO userVO = (SecUserVO)authentication.getPrincipal(); -// userVO.setAuthKey(req.getSession().getId()); // TODO : 임시로 세션ID 넣음, 실제 Authkey 생성 규칙에 따른 해당 키 설정 처리 필요 -// -// // 실제 SecurityContext 에 authentication 정보를 등록한다. -// SecurityContextHolder.getContext().setAuthentication(authentication); -// -// // TODO : 로그인 로그 정보를 통합자료시스템에 전송한다. -// -// } catch (DisabledException e) { -// return "/login/loginForm.do?error=locked"; -// } catch (LockedException e) { -// return "/login/loginForm.do?error=disable"; -// } catch (BadCredentialsException e) { -// return "/login/loginForm.do?error=invalid-password"; -// } catch (Exception e) { -// return "/login/loginForm.do?error=other." + e.toString(); -// } + // 아이디와 패스워드로, Security 가 알아 볼 수 있는 token 객체로 변경한다. + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(nLoginVO.getLoginUserId(), nLoginVO.getUserPwd()); + + try { + // AuthenticationManager 에 token 을 넘기면 UserDetailsService 가 받아 처리하도록 한다. + Authentication authentication = authenticationManager.authenticate(token); + + // AuthKey 등록 + SecUserVO userVO = (SecUserVO)authentication.getPrincipal(); + userVO.getAndCreateAuthKey(req.getSession().getId()); // SET AUTHKEY + + // 실제 SecurityContext 에 authentication 정보를 등록한다. + SecurityContextHolder.getContext().setAuthentication(authentication); + + // TODO : 로그인 로그 정보를 통합자료시스템에 전송한다. + userVO.setAccIp(req.getRemoteAddr()); + userVO.setLoginSucsYn("Y"); + loginDAO.insertLoginLog(userVO); + + } catch (DisabledException e) { + return "/login/loginForm.do?error=locked"; + } catch (LockedException e) { + return "/login/loginForm.do?error=disable"; + } catch (BadCredentialsException e) { + return "/login/loginForm.do?error=invalid-password"; + } catch (Exception e) { + return "/login/loginForm.do?error=other&message=" + e.toString(); + } return null; } diff --git a/src/main/java/nlib/user/web/LoginController.java b/src/main/java/nlib/user/web/LoginController.java index 26b8903e..65bbfd99 100644 --- a/src/main/java/nlib/user/web/LoginController.java +++ b/src/main/java/nlib/user/web/LoginController.java @@ -49,6 +49,7 @@ import egovframework.com.ext.oauth.service.OAuthConfig; import egovframework.com.ext.oauth.service.OAuthLogin; import egovframework.com.ext.oauth.service.OAuthUniversalUser; import egovframework.com.ext.oauth.service.OAuthVO; +import nlib.cmm.service.NlibProperty; import nlib.cmm.snslogin.GoogleOAuthResponse; import nlib.cmm.snslogin.KakaoController; import nlib.cmm.snslogin.NaverLoginBO; @@ -178,7 +179,7 @@ public class LoginController { // } // @RequestMapping(value = "/login/{oauthService}Callback.do", method = { RequestMethod.GET, RequestMethod.POST}) - public String oauthLoginCallback(@PathVariable String oauthService, + public String oauthLoginCallback(HttpServletRequest req, @PathVariable String oauthService, Model model, @RequestParam String code, HttpSession session) throws Exception { String redirectUrl = "/index.do"; @@ -204,23 +205,24 @@ public class LoginController { OAuthUniversalUser oauthUser = oauthLogin.getUserProfile(code); // 1,2번 동시 log.debug("Profile ===>>" + oauthUser); - String resultDBInfo = loginService.loginOauth(oauthUser.getUid()); + String loginResult = loginService.loginOauth(req, oauthUser.getUid()); // oAuth를 통한 SNS연동이 실패한 경우 if(oauthUser == null || !oauthUser.isValid()) { - model.addAttribute("code", "NOMEM"); model.addAttribute("message", "먼저 회원가입하신 후, 이용하여 주시기 바랍니다."); - } - // SNS 로그인은 정상적이나, NLIB 시스템에 등록되지 않은 사용자 : 회원가입으로 전환 - else if(oauthUser.isValid() && resultDBInfo == null) { - model.addAttribute("code", "GONEW"); - model.addAttribute("message", "먼저 회원가입하신 후, 이용 가능합니다. 해당 SNS 계정 정보로 회원가입을 진행하시겠습니까?"); + redirectUrl = NlibProperty.getString("member.new.url"); // "/member/insertMemberInfoForm.do" } // 정상 SNS 연동 로그인 - else if(oauthUser.isValid() && resultDBInfo != null) { + else if(oauthUser.isValid() && loginResult == null) { // 세션에 설정된 redirect 주소 확인 model.addAttribute("message", "정상적으로 로그인되었습니다."); } + // SNS 로그인은 정상적이나, NLIB 시스템에 등록되지 않은 사용자 : 회원가입으로 전환 + else { + model.addAttribute("code", "GONEW"); + model.addAttribute("message", "먼저 회원가입하신 후, 이용 가능합니다. 해당 SNS 계정 정보로 회원가입을 진행하시겠습니까?"); + redirectUrl = loginResult; + } return "redirect:" + redirectUrl; } diff --git a/src/main/resources/egovframework/mapper/config/mapper-config.xml b/src/main/resources/egovframework/mapper/config/mapper-config.xml index 17568b6e..6a706d7f 100644 --- a/src/main/resources/egovframework/mapper/config/mapper-config.xml +++ b/src/main/resources/egovframework/mapper/config/mapper-config.xml @@ -13,6 +13,7 @@ + \ No newline at end of file diff --git a/src/main/resources/egovframework/mapper/nlib/user/LoginDAO_SQL.xml b/src/main/resources/egovframework/mapper/nlib/user/LoginDAO_SQL.xml new file mode 100644 index 00000000..4489e05f --- /dev/null +++ b/src/main/resources/egovframework/mapper/nlib/user/LoginDAO_SQL.xml @@ -0,0 +1,43 @@ + + + + + + + + INSERT INTO SM_ACC_LOG /* 접속로그 */ + ( USER_ID + ,USER_NM + ,DEPT_SEQ + ,DEPT_NM + ,ACC_IP + ,LOGIN_SUCS_YN + ,ACC_DATE + ) VALUES ( + #{userId} + ,#{userNm} + ,#{deptSeq} + ,#{deptNm} + ,#{accIp} + ,#{loginSucsYn} + ,NOW() + ) + + + \ No newline at end of file diff --git a/src/main/resources/egovframework/mapper/nlib/user/SecUserDAO_SQL.xml b/src/main/resources/egovframework/mapper/nlib/user/SecUserDAO_SQL.xml new file mode 100644 index 00000000..41dc45e3 --- /dev/null +++ b/src/main/resources/egovframework/mapper/nlib/user/SecUserDAO_SQL.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/nlib/nlib.properties b/src/main/resources/nlib/nlib.properties index 0062fe1f..2e5c1f71 100644 --- a/src/main/resources/nlib/nlib.properties +++ b/src/main/resources/nlib/nlib.properties @@ -91,3 +91,20 @@ oauth2.client.provider.naver.token-uri = https://nid.naver.com/oauth2.0/token oauth2.client.provider.naver.user-info-uri = https://openapi.naver.com/v1/nid/me oauth2.client.provider.naver.user-name-attribute = response + +#---------------------------------------- +# \ub85c\uadf8\uc778/\ud68c\uc6d0\uac00\uc785\uad00\ub828 URL \uc815\ubcf4 +#---------------------------------------- +member.new.url = /member/insertMemberInfoForm.do +member.login.url = /member/insertMemberInfoForm.do + + +#---------------------------------------- +# \uc0ac\uc6a9\uc790\uad8c\ud55c\uba85 +#---------------------------------------- +# \uc77c\ubc18\uc0ac\uc6a9\uc790 +auth.role.user = ROLE_USER +# \uad00\ub9ac\uc790 +auth.role.admin = ROLE_ADMIN +# \uc2dc\uc2a4\ud15c\uad00\ub9ac\uc790 +auth.role.system = ROLE_SYSTEM