diff --git a/pom.xml b/pom.xml index a54739b4..5206bb4a 100644 --- a/pom.xml +++ b/pom.xml @@ -141,6 +141,18 @@ commons-httpclient 3.1 + + + org.springframework + spring-core + ${spring.maven.artifact.version} + + + + org.springframework + spring-expression + ${spring.maven.artifact.version} + @@ -155,8 +167,17 @@ --> - + + + org.springframework.webflow + spring-faces + 2.4.1.RELEASE + org.springframework.security spring-security-web diff --git a/src/main/java/egovframework/com/ext/oauth/service/OAuthLogin.java b/src/main/java/egovframework/com/ext/oauth/service/OAuthLogin.java index 12575d38..5ce7211f 100644 --- a/src/main/java/egovframework/com/ext/oauth/service/OAuthLogin.java +++ b/src/main/java/egovframework/com/ext/oauth/service/OAuthLogin.java @@ -20,7 +20,9 @@ public class OAuthLogin { private OAuth20Service oauthService; private OAuthVO oauthVO; + public OAuthLogin(OAuthVO oauthVO) { + this.oauthService = new ServiceBuilder(oauthVO.getClientId()) .apiSecret(oauthVO.getClientSecret()) .callback(oauthVO.getRedirectUrl()) @@ -30,6 +32,17 @@ public class OAuthLogin { this.oauthVO = oauthVO; } + public OAuthLogin(OAuthVO oauthVO, String deptJsessionId) { + + this.oauthService = new ServiceBuilder(oauthVO.getClientId()) + .apiSecret(oauthVO.getClientSecret()) + .callback(appendParam(oauthVO.getRedirectUrl(), "deptJsessionId", deptJsessionId)) + .scope("profile") + .build(oauthVO.getApi20Instance()); + + this.oauthVO = oauthVO; + } + public String getOAuthURL() { return this.oauthService.getAuthorizationUrl(); } @@ -100,6 +113,9 @@ public class OAuthLogin { // 성별 user.setGender(resNode.get("gender").asText()); + // 로그인 성공 + user.setValidLogin(true); + } else if (this.oauthVO.isKakao()) { user.setServiceName(OAuthConfig.KAKAO_SERVICE_NAME); JsonNode resNode = rootNode.get("properties"); @@ -110,4 +126,18 @@ public class OAuthLogin { return user; } + public String appendParam(String url, String paramName, String paramValue) { + if(StringUtil.isEmpty(url)) return ""; + if(StringUtil.isEmpty(paramName)) return url; + + if(StringUtil.isEmpty(paramValue)) paramValue = ""; + + if(url.contains("?")) url += "&"; + else url += "?"; + + url += paramName + "=" + paramValue; + + return url; + } + } diff --git a/src/main/java/egovframework/com/ext/oauth/service/OAuthUniversalUser.java b/src/main/java/egovframework/com/ext/oauth/service/OAuthUniversalUser.java index 9d42345e..052033d2 100644 --- a/src/main/java/egovframework/com/ext/oauth/service/OAuthUniversalUser.java +++ b/src/main/java/egovframework/com/ext/oauth/service/OAuthUniversalUser.java @@ -20,6 +20,7 @@ public class OAuthUniversalUser { private String loginIp; private Date lastLogin; + private boolean isValidLogin = false; public boolean isValid() { return StringUtil.isNotEmpty(uid) && StringUtil.isNotEmpty(userId); @@ -121,4 +122,12 @@ public class OAuthUniversalUser { this.gender = gender; } + public boolean isValidLogin() { + return isValidLogin; + } + + public void setValidLogin(boolean isValidLogin) { + this.isValidLogin = isValidLogin; + } + } diff --git a/src/main/java/nlib/cmm/qrcode/QRCodeUtil.java b/src/main/java/nlib/cmm/qrcode/QRCodeUtil.java index f0fbbac5..e2f3d6db 100644 --- a/src/main/java/nlib/cmm/qrcode/QRCodeUtil.java +++ b/src/main/java/nlib/cmm/qrcode/QRCodeUtil.java @@ -149,7 +149,6 @@ public class QRCodeUtil { // (2) 앞의 (1)의 문자열을 암호화 처리 String cryptedBarcodeText = EgovFileScrty.encodeBinary(barcodeText.getBytes()); log.debug("generateMemberQRCodeImage : cryptedBarcodeText=" + cryptedBarcodeText); - loginVO.setOnnaraUserid(cryptedBarcodeText); // TODO 임시저장처리 DDDDDDDDDDDDDDDDDDDDDDD // (3) 앞의 (2) 암호화 문자열로 QRCode 생성하여 BufferedImage형식으로 리턴 return generateQRCodeImageByZxing(cryptedBarcodeText); diff --git a/src/main/java/nlib/cmm/service/NlibProperty.java b/src/main/java/nlib/cmm/service/NlibProperty.java index 560fd8a0..a538ba1d 100644 --- a/src/main/java/nlib/cmm/service/NlibProperty.java +++ b/src/main/java/nlib/cmm/service/NlibProperty.java @@ -109,7 +109,10 @@ public class NlibProperty { if(loadProperties() < 0) return null; } - return properties.getProperty(name); + String value = properties.getProperty(name); + if(value != null) value = value.trim(); + + return value; } /** diff --git a/src/main/java/nlib/cmm/session/SessionConfig.java b/src/main/java/nlib/cmm/session/SessionConfig.java new file mode 100644 index 00000000..a52e396a --- /dev/null +++ b/src/main/java/nlib/cmm/session/SessionConfig.java @@ -0,0 +1,72 @@ +package nlib.cmm.session; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.annotation.WebListener; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; + +import nlib.user.service.impl.LoginServiceImpl; +import nlib.util.StringUtil; + +@WebListener +public class SessionConfig implements HttpSessionListener { + + private static final Logger log = LoggerFactory.getLogger(LoginServiceImpl.class); + + private static final Map sessions = new ConcurrentHashMap<>(); +// +// //중복로그인 지우기 +// public synchronized static String getSessionidCheck(String type, String compareId){ +// String result = ""; +// for( String key : sessions.keySet() ){ +// HttpSession hs = sessions.get(key); +// if(hs != null && hs.getAttribute(type) != null && hs.getAttribute(type).toString().equals(compareId) ){ +// result = key.toString(); +// } +// } +// removeSessionForDoubleLogin(result); +// return result; +// } +// +// private static void removeSessionForDoubleLogin(String userId){ +// System.out.println("remove userId : " + userId); +// if(userId != null && userId.length() > 0){ +// sessions.get(userId).invalidate(); +// sessions.remove(userId); +// } +// } +// + + @Override + public void sessionCreated(HttpSessionEvent se) { + System.out.println("Session sessionCreated (O) : " + se.getSession().getId()); + } + + @Override + public void sessionDestroyed(HttpSessionEvent se) { + log.debug("Session sessionDestroyed (X) : " + se.getSession().getId()); + if(sessions.get(se.getSession().getId()) != null){ + //sessions.get(se.getSession().getId()).invalidate(); + sessions.remove(se.getSession().getId()); + } + } + + public static String getLoginInfo(String sessionId) { + if(StringUtil.isEmpty(sessionId)) return null; + + return sessions.get(sessionId); + } + + public static void setLoginInfo(String sessionId, String snsUserId) { + sessions.put(sessionId, snsUserId); + } + +} \ No newline at end of file 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/security/SpringSecurityConfig.java b/src/main/java/nlib/security/SpringSecurityConfig.java index dbc0d02a..8a6eb302 100644 --- a/src/main/java/nlib/security/SpringSecurityConfig.java +++ b/src/main/java/nlib/security/SpringSecurityConfig.java @@ -45,6 +45,8 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { + + // 권한/인증과 무관한 오픈된 정적 리소트 web.ignoring() .antMatchers("/resources/**") .antMatchers("/css/**") @@ -52,13 +54,6 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { .antMatchers("/js/**") .antMatchers("/temp/**") .antMatchers("/favicon/**") - .antMatchers("/*/*Ajax.do") - .antMatchers("/fileupload/**") - .antMatchers("/board/**") - .antMatchers("/inform/**") - .antMatchers("/alert/**") - .antMatchers("/code/**") - .antMatchers("/**") ; } @@ -82,6 +77,14 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { .antMatchers("/rent/*.do").permitAll() .antMatchers("/collection/*.do").permitAll() .antMatchers("/sample/password/getSampleEncoder.do").permitAll() + .antMatchers("/*/*Ajax.do").permitAll() + .antMatchers("/fileupload/**").permitAll() + .antMatchers("/board/**").permitAll() + .antMatchers("/inform/**").permitAll() + .antMatchers("/alert/**").permitAll() + .antMatchers("/code/**").permitAll() + .antMatchers("/homes/**").permitAll() + .antMatchers("/homes/**").permitAll() .anyRequest().authenticated() .and().formLogin() .loginPage("/login/loginForm.do") diff --git a/src/main/java/nlib/user/service/LoginService.java b/src/main/java/nlib/user/service/LoginService.java index 836d34a0..cbdfcf5e 100644 --- a/src/main/java/nlib/user/service/LoginService.java +++ b/src/main/java/nlib/user/service/LoginService.java @@ -10,7 +10,11 @@ public interface LoginService { public String login(HttpServletRequest req, String username, String password); - public String loginOauth(String snsUid); + public String loginOauth(HttpServletRequest req, String snsUserId, String deptJsessionId); + + public String loginDeptSSO(HttpServletRequest req, String snsUserId); + + public String loginDept(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..6dfa17d7 100644 --- a/src/main/java/nlib/user/service/NlibLoginVO.java +++ b/src/main/java/nlib/user/service/NlibLoginVO.java @@ -35,41 +35,28 @@ public class NlibLoginVO implements Serializable { private String userId; /* 사용자아이디 (ex: U1000000001) */ private String loginUserId; /* 로그인사용자ID (이메일주소) */ private String deptSeq; /* 조직코드 */ - private String userDiv; /* 사용자구분 */ + private String deptNm; /* 조직명 */ private String userNm; /* 사용자명 */ private String userPwd; /* 비밀번호 */ - private String posNm; /* 직위 */ - private String rank; /* 직급 */ - private String workFlag; /* 근무여부 */ private String telNo; /* 전화번호 */ private String zipcode; /* 우편번호 (변경예정) */ private String addr1; /* 주소1 (변경예정) */ private String addr2; /* 주소2 (변경예정) */ - private String strtMenuSeq; /* 시작페이지 */ - private String idCardChkYn; /* 신분증 확인여부 */ - private String useYn; /* 사용여부 */ - private String ssoFlag; /* 시스템구분(1:기록관리,2:기관배치) */ - private String loginErrorCnt; /* 로그인오류건수 */ - private String onnaraUserid; /* 온나라사용자아이디(웹서비스용) */ - private String pkiNameCheck; /* 인증서 등록시 이름 체크 구분 */ - private String ssoKey; /* SSO 인증KEY (SSO를 위한 사용자의 KEY값) */ + private String status; /* 상태 : S정상, D탈퇴, P휴면 */ private String regId; /* 등록자 */ private String regDd; /* 등록일자 */ private String modId; /* 수정자 */ private String modDd; /* 수정일자 */ private String email; /* 이메일 */ private String mobileNo; /* 모바일 */ - private String websiteAddr; /* 웹사이트 */ - private String facebookId; /* 페이스북아이디 */ - private String twitterId; /* 트위터아이디 */ - private String googleId; /* 구글플러스아이디 */ - private String boardRowCnt; /* 글목록수 */ private String birthdate; /* 생년월일 */ private String gender; /* 성별(M:남자,F:여자) */ private String authKey; /* 로그인 인증키 */ - + private String loginSucsYn; /* 로그인성공여부 */ + private String accIp; /* 접속IP */ + private String authorityList; /* 권한ROLE 리스트 */ /** * 로그인인증키값을 리턴한다. 만일 존재하지 않을 경우, userId를 기반으로 인증키를 생성하여 리턴한다. @@ -95,9 +82,11 @@ public class NlibLoginVO implements Serializable { return this.authKey; } + //---------------------------------------------------------------- // SETTER.GETTER //---------------------------------------------------------------- + public String getUserId() { return userId; } @@ -122,18 +111,22 @@ public class NlibLoginVO implements Serializable { this.deptSeq = deptSeq; } - public String getUserDiv() { - return userDiv; + public String getDeptNm() { + return deptNm; } - public void setUserDiv(String userDiv) { - this.userDiv = userDiv; + public void setDeptNm(String deptNm) { + this.deptNm = deptNm; } public String getUserNm() { return userNm; } + public String getName() { + return userNm; + } + public void setUserNm(String userNm) { this.userNm = userNm; } @@ -146,30 +139,6 @@ public class NlibLoginVO implements Serializable { this.userPwd = userPwd; } - public String getPosNm() { - return posNm; - } - - public void setPosNm(String posNm) { - this.posNm = posNm; - } - - public String getRank() { - return rank; - } - - public void setRank(String rank) { - this.rank = rank; - } - - public String getWorkFlag() { - return workFlag; - } - - public void setWorkFlag(String workFlag) { - this.workFlag = workFlag; - } - public String getTelNo() { return telNo; } @@ -202,68 +171,12 @@ public class NlibLoginVO implements Serializable { this.addr2 = addr2; } - public String getStrtMenuSeq() { - return strtMenuSeq; + public String getStatus() { + return status; } - public void setStrtMenuSeq(String strtMenuSeq) { - this.strtMenuSeq = strtMenuSeq; - } - - public String getIdCardChkYn() { - return idCardChkYn; - } - - public void setIdCardChkYn(String idCardChkYn) { - this.idCardChkYn = idCardChkYn; - } - - public String getUseYn() { - return useYn; - } - - public void setUseYn(String useYn) { - this.useYn = useYn; - } - - public String getSsoFlag() { - return ssoFlag; - } - - public void setSsoFlag(String ssoFlag) { - this.ssoFlag = ssoFlag; - } - - public String getLoginErrorCnt() { - return loginErrorCnt; - } - - public void setLoginErrorCnt(String loginErrorCnt) { - this.loginErrorCnt = loginErrorCnt; - } - - public String getOnnaraUserid() { - return onnaraUserid; - } - - public void setOnnaraUserid(String onnaraUserid) { - this.onnaraUserid = onnaraUserid; - } - - public String getPkiNameCheck() { - return pkiNameCheck; - } - - public void setPkiNameCheck(String pkiNameCheck) { - this.pkiNameCheck = pkiNameCheck; - } - - public String getSsoKey() { - return ssoKey; - } - - public void setSsoKey(String ssoKey) { - this.ssoKey = ssoKey; + public void setStatus(String status) { + this.status = status; } public String getRegId() { @@ -314,55 +227,6 @@ public class NlibLoginVO implements Serializable { this.mobileNo = mobileNo; } - public String getWebsiteAddr() { - return websiteAddr; - } - - public void setWebsiteAddr(String websiteAddr) { - this.websiteAddr = websiteAddr; - } - - public String getFacebookId() { - return facebookId; - } - - public void setFacebookId(String facebookId) { - this.facebookId = facebookId; - } - - public String getTwitterId() { - return twitterId; - } - - public void setTwitterId(String twitterId) { - this.twitterId = twitterId; - } - - public String getGoogleId() { - return googleId; - } - - public void setGoogleId(String googleId) { - this.googleId = googleId; - } - - public String getBoardRowCnt() { - return boardRowCnt; - } - - public void setBoardRowCnt(String boardRowCnt) { - this.boardRowCnt = boardRowCnt; - } - - public String getAuthKey() { - - return authKey; - } - - public void setAuthKey(String authKey) { - this.authKey = authKey; - } - public String getBirthdate() { return birthdate; } @@ -378,5 +242,37 @@ public class NlibLoginVO implements Serializable { public void setGender(String gender) { this.gender = gender; } + + public String getAuthKey() { + return authKey; + } + + public void setAuthKey(String authKey) { + this.authKey = authKey; + } + + public String getLoginSucsYn() { + return loginSucsYn; + } + + public void setLoginSucsYn(String loginSucsYn) { + this.loginSucsYn = loginSucsYn; + } + + public String getAccIp() { + return accIp; + } + + public void setAccIp(String accIp) { + this.accIp = accIp; + } + + 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..81cc39c1 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("LoginDAO.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..cd99ff29 100644 --- a/src/main/java/nlib/user/service/impl/LoginServiceImpl.java +++ b/src/main/java/nlib/user/service/impl/LoginServiceImpl.java @@ -13,13 +13,16 @@ import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import nlib.cmm.session.SessionConfig; 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,17 +75,25 @@ public class LoginServiceImpl implements LoginService } - /* - * SNS 연동을 통한 로그인 처리를 수행한다. + /* SNS 연동 SSO를 통한 로그인 처리한다. + * + * return값이 null인 경우, 정상적인 로그인 처리 완료 + * null이 아닌 경우, REDIRECT되어야 하는 URL(오류 코드 포함) * */ - public String loginOauth(String snsUid) { - - // SNS 연동 사용자UID로 사용자정보 조회 - if(StringUtil.isEmpty(snsUid)) return null; - +// public String loginOauth(HttpServletRequest req, String snsUserId) { +// +// // SNS 연동 사용자UID로 사용자정보 조회 +// 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); +// UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(nLoginVO.getLoginUserId(), nLoginVO.getUserPwd()); // // try { // // AuthenticationManager 에 token 을 넘기면 UserDetailsService 가 받아 처리하도록 한다. @@ -90,22 +101,179 @@ public class LoginServiceImpl implements LoginService // // // AuthKey 등록 // SecUserVO userVO = (SecUserVO)authentication.getPrincipal(); -// userVO.setAuthKey(req.getSession().getId()); // TODO : 임시로 세션ID 넣음, 실제 Authkey 생성 규칙에 따른 해당 키 설정 처리 필요 +// 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) { +// e.printStackTrace(); // return "/login/loginForm.do?error=locked"; // } catch (LockedException e) { +// e.printStackTrace(); // return "/login/loginForm.do?error=disable"; // } catch (BadCredentialsException e) { +// e.printStackTrace(); // return "/login/loginForm.do?error=invalid-password"; // } catch (Exception e) { -// return "/login/loginForm.do?error=other." + e.toString(); +// e.printStackTrace(); +// return "/login/loginForm.do?error=other&message=" + e.toString(); // } +// +// return null; +// } +// + + /* SNS 연동 SSO를 통한 로그인 처리한다. + * + * return값이 null인 경우, 정상적인 로그인 처리 완료 + * null이 아닌 경우, REDIRECT되어야 하는 URL(오류 코드 포함) + * + */ + public String loginOauth(HttpServletRequest req, String snsUserId, String deptJsessionId) { + + // SNS 연동 사용자UID로 사용자정보 조회 + 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(nLoginVO.getLoginUserId(), nLoginVO.getUserPwd()); + + try { + // AuthenticationManager 에 token 을 넘기면 UserDetailsService 가 받아 처리하도록 한다. + Authentication authentication = authenticationManager.authenticate(token); + + if(authentication.isAuthenticated()) { + SessionConfig.setLoginInfo(deptJsessionId, snsUserId); + } else { + SessionConfig.setLoginInfo(deptJsessionId, null); + } + + } catch (DisabledException e) { + e.printStackTrace(); + return "/login/loginForm.do?error=locked"; + } catch (LockedException e) { + e.printStackTrace(); + return "/login/loginForm.do?error=disable"; + } catch (BadCredentialsException e) { + e.printStackTrace(); + return "/login/loginForm.do?error=invalid-password"; + } catch (Exception e) { + e.printStackTrace(); + return "/login/loginForm.do?error=other&message=" + e.toString(); + } + + return null; + } + + public String loginDeptSSO(HttpServletRequest req, String snsUserId) { + + // SNS 연동 사용자UID로 사용자정보 조회 + 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(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) { + e.printStackTrace(); + return "/login/loginForm.do?error=locked"; + } catch (LockedException e) { + e.printStackTrace(); + return "/login/loginForm.do?error=disable"; + } catch (BadCredentialsException e) { + e.printStackTrace(); + return "/login/loginForm.do?error=invalid-password"; + } catch (Exception e) { + e.printStackTrace(); + return "/login/loginForm.do?error=other&message=" + e.toString(); + } + + return null; + } + + + + /* SNS 연동 SSO를 통한 로그인 처리한다. + * + * return값이 null인 경우, 정상적인 로그인 처리 완료 + * null이 아닌 경우, REDIRECT되어야 하는 URL(오류 코드 포함) + * + */ + public String loginDept(HttpServletRequest req, String snsUserId) { + + // SNS 연동 사용자UID로 사용자정보 조회 + 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(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) { + e.printStackTrace(); + return "/login/loginForm.do?error=locked"; + } catch (LockedException e) { + e.printStackTrace(); + return "/login/loginForm.do?error=disable"; + } catch (BadCredentialsException e) { + e.printStackTrace(); + return "/login/loginForm.do?error=invalid-password"; + } catch (Exception e) { + e.printStackTrace(); + 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..743d648d 100644 --- a/src/main/java/nlib/user/web/LoginController.java +++ b/src/main/java/nlib/user/web/LoginController.java @@ -1,8 +1,6 @@ package nlib.user.web; -import java.io.IOException; -import java.net.URI; import java.util.Map; import javax.annotation.Resource; @@ -12,46 +10,26 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.lang3.StringUtils; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -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; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.util.UriComponentsBuilder; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; -import com.github.scribejava.core.model.OAuth2AccessToken; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; 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.snslogin.GoogleOAuthResponse; -import nlib.cmm.snslogin.KakaoController; -import nlib.cmm.snslogin.NaverLoginBO; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.session.SessionConfig; import nlib.user.service.LoginService; import nlib.util.StringUtil; @@ -119,31 +97,86 @@ public class LoginController { * @return */ @RequestMapping("/login/loginForm.do") - public String loginForm(HttpServletRequest req, @RequestParam(required = false) String error, - @RequestParam(required = false) String logout, Model model, HttpSession session) { - if (error != null) { - model.addAttribute("error", String.format("ID와 비밀번호를 확인하여 주시기 바랍니다. %s", error)); - } - if (logout != null) { - model.addAttribute("logout", String.format("로그아웃하였습니다 %s", logout)); - } + public String loginForm(HttpServletRequest req, + @RequestParam(required = false) String error, + @RequestParam(required = false) String message, + @RequestParam(required = false) String logout, + RedirectAttributes redirectAttrs, + @RequestParam Map paramMap, + Model model, + HttpSession session) { + //---------------------------------------------- + // 지방문화원 사이트에서 접속한 경우, 지방문화원 정보 확인 + //---------------------------------------------- + String deptJsessionId = paramMap.get("deptJsessionId"); + String deptHostName = paramMap.get("deptHostName"); + String deptReturnUrl = paramMap.get("deptReturnUrl"); + String deptHomeUrl = paramMap.get("deptHomeUrl"); + + log.debug("loginForm > deptJsessionId = " + deptJsessionId); + log.debug("loginForm > deptHostName = " + deptHostName); + log.debug("loginForm > deptReturnUrl = " + deptReturnUrl); + log.debug("loginForm > deptHomeUrl = " + deptHomeUrl); + + session.setAttribute("deptJsessionId", deptJsessionId); + session.setAttribute("deptHostName", deptHostName); + session.setAttribute("deptReturnUrl", (StringUtil.isNotEmpty(deptReturnUrl) ? StringUtil.decodeBase64(deptReturnUrl) : null)); + session.setAttribute("deptHomeUrl", (StringUtil.isNotEmpty(deptHomeUrl) ? StringUtil.decodeBase64(deptHomeUrl) : null)); + + //---------------------------------------------- // SNS 연동 URL 생성 - OAuthLogin naverLogin = new OAuthLogin(naverAuthVO); + //---------------------------------------------- + OAuthLogin naverLogin = new OAuthLogin(naverAuthVO, deptJsessionId); log.debug("naverLogin.getOAuthURL() = "+naverLogin.getOAuthURL()); model.addAttribute("naverUrl", naverLogin.getOAuthURL()); - OAuthLogin googleLogin = new OAuthLogin(googleAuthVO); + OAuthLogin googleLogin = new OAuthLogin(googleAuthVO, deptJsessionId); log.debug("googleLogin.getOAuthURL() = "+googleLogin.getOAuthURL()); model.addAttribute("googleUrl", googleLogin.getOAuthURL()); - OAuthLogin kakaoLogin = new OAuthLogin(kakaoAuthVO); + OAuthLogin kakaoLogin = new OAuthLogin(kakaoAuthVO, deptJsessionId); log.debug("kakaoLogin.getOAuthURL() = "+kakaoLogin.getOAuthURL()); model.addAttribute("kakaoUrl", kakaoLogin.getOAuthURL()); + model.addAttribute("error", error); + model.addAttribute("message", message); + model.addAttribute("logout", String.format("로그아웃하였습니다 %s", logout)); + return "nlib/login/loginForm"; } +// @RequestMapping("/login/loginForm.do") +// public String loginForm(HttpServletRequest req, +// @RequestParam(required = false) String error, +// @RequestParam(required = false) String message, +// @RequestParam(required = false) String logout, +// Model model, +// HttpSession session) { +// +// +// model.addAttribute("error", error); +// model.addAttribute("message", message); +// model.addAttribute("logout", String.format("로그아웃하였습니다 %s", logout)); +// +// // SNS 연동 URL 생성 +// OAuthLogin naverLogin = new OAuthLogin(naverAuthVO); +// log.debug("naverLogin.getOAuthURL() = "+naverLogin.getOAuthURL()); +// model.addAttribute("naverUrl", naverLogin.getOAuthURL()); +// +// OAuthLogin googleLogin = new OAuthLogin(googleAuthVO); +// log.debug("googleLogin.getOAuthURL() = "+googleLogin.getOAuthURL()); +// model.addAttribute("googleUrl", googleLogin.getOAuthURL()); +// +// OAuthLogin kakaoLogin = new OAuthLogin(kakaoAuthVO); +// log.debug("kakaoLogin.getOAuthURL() = "+kakaoLogin.getOAuthURL()); +// model.addAttribute("kakaoUrl", kakaoLogin.getOAuthURL()); +// +// model.addAttribute("coutTest", "서울시 마포구"); +// +// return "nlib/login/loginForm"; +// } + // @RequestMapping("/login/loginForm_BK20210817.do") // public String loginForm_BK20210817(HttpServletRequest req, @RequestParam(required = false) String error, // @RequestParam(required = false) String logout, Model model, HttpSession session) { @@ -177,52 +210,70 @@ public class LoginController { // return "nlib/login/loginForm"; // } // - @RequestMapping(value = "/login/{oauthService}Callback.do", method = { RequestMethod.GET, RequestMethod.POST}) - public String oauthLoginCallback(@PathVariable String oauthService, - Model model, @RequestParam String code, HttpSession session) throws Exception { - - String redirectUrl = "/index.do"; - - log.debug("oauthLoginCallback: service={}", oauthService); - log.debug("===>>> code = "+ code); - - OAuthVO oauthVO = null; - if (StringUtils.equals(OAuthConfig.GOOGLE_SERVICE_NAME, oauthService)) - oauthVO = googleAuthVO; - else if (StringUtils.equals(OAuthConfig.NAVER_SERVICE_NAME, oauthService)) - oauthVO = naverAuthVO; - else if (StringUtils.equals(OAuthConfig.KAKAO_SERVICE_NAME, oauthService)) - oauthVO = kakaoAuthVO; - else { - throw new Exception("SNS 연동 콜백정보가 올바르지 않습니다."); - } - - // 1. code를 이용해서 Access Token 받기 - // 2. Access Token을 이용해서 사용자 제공정보 가져오기 - OAuthLogin oauthLogin = new OAuthLogin(oauthVO); - - OAuthUniversalUser oauthUser = oauthLogin.getUserProfile(code); // 1,2번 동시 - log.debug("Profile ===>>" + oauthUser); - - String resultDBInfo = loginService.loginOauth(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 계정 정보로 회원가입을 진행하시겠습니까?"); - } - // 정상 SNS 연동 로그인 - else if(oauthUser.isValid() && resultDBInfo != null) { - // 세션에 설정된 redirect 주소 확인 - model.addAttribute("message", "정상적으로 로그인되었습니다."); - } - return "redirect:" + redirectUrl; - } +// @RequestMapping(value = "/login/{oauthService}Callback.do", method = { RequestMethod.GET, RequestMethod.POST}) +// public String oauthLoginCallback( +// HttpServletRequest req, +// @PathVariable String oauthService, +// Model model, +// @RequestParam String code, +// @RequestParam Map paramMap, +// HttpSession session) throws Exception { +// +// String redirectUrl = "/index.do"; +// +// log.debug("oauthLoginCallback: service={}", oauthService); +// log.debug("===>>> code = "+ code); +// +// OAuthVO oauthVO = null; +// if (StringUtils.equals(OAuthConfig.GOOGLE_SERVICE_NAME, oauthService)) +// oauthVO = googleAuthVO; +// else if (StringUtils.equals(OAuthConfig.NAVER_SERVICE_NAME, oauthService)) +// oauthVO = naverAuthVO; +// else if (StringUtils.equals(OAuthConfig.KAKAO_SERVICE_NAME, oauthService)) +// oauthVO = kakaoAuthVO; +// else { +// throw new Exception("SNS 연동 콜백정보가 올바르지 않습니다."); +// } +// +// // 1. code를 이용해서 Access Token 받기 +// // 2. Access Token을 이용해서 사용자 제공정보 가져오기 +// String deptJsessionId = paramMap.get("deptJsessionId"); +// OAuthLogin oauthLogin = new OAuthLogin(oauthVO, deptJsessionId); +// +// OAuthUniversalUser oauthUser = oauthLogin.getUserProfile(code); // 1,2번 동시 +// log.debug("Profile ===>>" + oauthUser); +// +// //----------------------------------------------------------------- +// // 호스트에 따른 별도 로그인 처리 +// //----------------------------------------------------------------- +// // 해당 호스트로 로그인처리 요청 +// //loginService.loginDept(req, oauthUser.getUid()); +// +// //----------------------------------------------------------------- +// +// String loginResult = loginService.loginOauth(req, oauthUser.getUid(), deptJsessionId); +// +// // oAuth를 통한 SNS연동이 실패한 경우 +// if(oauthUser == null || !oauthUser.isValid()) { +// model.addAttribute("message", "먼저 회원가입하신 후, 이용하여 주시기 바랍니다."); +// redirectUrl = NlibProperty.getString("member.new.url"); // "/member/insertMemberInfoForm.do" +// } +// // 정상 SNS 연동 로그인 +// else if(oauthUser.isValid() && loginResult == null) { +// // 세션에 설정된 redirect 주소 확인 +// model.addAttribute("message", "정상적으로 로그인되었습니다."); +// } +// // SNS 로그인은 정상적이나, NLIB 시스템에 등록되지 않은 사용자 : 회원가입으로 전환 +// else { +// model.addAttribute("code", "GONEW"); +// model.addAttribute("message", "먼저 회원가입하신 후, 이용 가능합니다. 해당 SNS 계정 정보로 회원가입을 진행하시겠습니까?"); +// redirectUrl = loginResult; +// } +// String deptReturnUrl = (String)session.getAttribute("deptReturnUrl"); +// if(StringUtil.isNotEmpty(deptReturnUrl)) redirectUrl = deptReturnUrl; +// +// return "redirect:" + redirectUrl; +// } // 네이버 로그인 성공시 callback호출 메소드 // @RequestMapping(value = "/login/naverCallback_BK20210817.do", method = { RequestMethod.GET, RequestMethod.POST }) @@ -326,6 +377,128 @@ public class LoginController { // }// end kakaoLogin() // + // @RequestMapping("/login/loginForm.do") + // public String loginForm(HttpServletRequest req, + // @RequestParam(required = false) String error, + // @RequestParam(required = false) String message, + // @RequestParam(required = false) String logout, + // Model model, + // HttpSession session) { + // + // + // model.addAttribute("error", error); + // model.addAttribute("message", message); + // model.addAttribute("logout", String.format("로그아웃하였습니다 %s", logout)); + // + // // SNS 연동 URL 생성 + // OAuthLogin naverLogin = new OAuthLogin(naverAuthVO); + // log.debug("naverLogin.getOAuthURL() = "+naverLogin.getOAuthURL()); + // model.addAttribute("naverUrl", naverLogin.getOAuthURL()); + // + // OAuthLogin googleLogin = new OAuthLogin(googleAuthVO); + // log.debug("googleLogin.getOAuthURL() = "+googleLogin.getOAuthURL()); + // model.addAttribute("googleUrl", googleLogin.getOAuthURL()); + // + // OAuthLogin kakaoLogin = new OAuthLogin(kakaoAuthVO); + // log.debug("kakaoLogin.getOAuthURL() = "+kakaoLogin.getOAuthURL()); + // model.addAttribute("kakaoUrl", kakaoLogin.getOAuthURL()); + // + // model.addAttribute("coutTest", "서울시 마포구"); + // + // return "nlib/login/loginForm"; + // } + + // @RequestMapping("/login/loginForm_BK20210817.do") + // public String loginForm_BK20210817(HttpServletRequest req, @RequestParam(required = false) String error, + // @RequestParam(required = false) String logout, Model model, HttpSession session) { + // if (error != null) { + // model.addAttribute("error", String.format("ID와 비밀번호를 확인하여 주시기 바랍니다. %s", error)); + // } + // if (logout != null) { + // model.addAttribute("logout", String.format("로그아웃하였습니다 %s", logout)); + // } + // // 네이버 로그인 URL 생성 + // /* 네이버아이디로 인증 URL을 생성하기 위하여 naverLoginBO클래스의 getAuthorizationUrl메소드 호출 */ + // naverLoginBO.setRedirect_url("http://nlib.nculture.org/nlib/login/naverCallback.do"); + // String naverAuthUrl = naverLoginBO.getAuthorizationUrl(session); + // + // // 구글 로그인 URL 생성 + // String googleUrl = "https://accounts.google.com/o/oauth2/v2/auth?" + // + "client_id=879126511006-jro7bld7b2epl3n5mkksp0p24k2inbpu.apps.googleusercontent.com" + // + "&redirect_uri=http://nlib.nculture.org/nlib/login/googleCallback.do" + // + "&response_type=code" + // + "&scope=email%20profile%20openid" + // + "&access_type=offline"; + // + // // 카카오 로그인 URL 생성 + // String k_redirect_url="http://nlib.nculture.org/nlib/login/kakaoCallback.do"; + // String kakaoUrl = KakaoController.getAuthorizationUrl(session,k_redirect_url); + // + // model.addAttribute("naverUrl", naverAuthUrl); + // model.addAttribute("googleUrl", googleUrl); + // model.addAttribute("kakaoUrl", kakaoUrl); + // + // return "nlib/login/loginForm"; + // } + // + @RequestMapping(value = "/login/{oauthService}Callback.do", method = { RequestMethod.GET, RequestMethod.POST}) + public String oauthLoginCallback( + HttpServletRequest req, + @PathVariable String oauthService, + Model model, + @RequestParam String code, + @RequestParam Map paramMap, + HttpSession session) throws Exception { + + String redirectUrl = "/index.do"; + + log.debug("oauthLoginCallback: service={}", oauthService); + log.debug("===>>> code = "+ code); + + OAuthVO oauthVO = null; + if (StringUtils.equals(OAuthConfig.GOOGLE_SERVICE_NAME, oauthService)) + oauthVO = googleAuthVO; + else if (StringUtils.equals(OAuthConfig.NAVER_SERVICE_NAME, oauthService)) + oauthVO = naverAuthVO; + else if (StringUtils.equals(OAuthConfig.KAKAO_SERVICE_NAME, oauthService)) + oauthVO = kakaoAuthVO; + else { + throw new Exception("SNS 연동 콜백정보가 올바르지 않습니다."); + } + + String deptJsessionId = paramMap.get("deptJsessionId"); + + // 1. code를 이용해서 Access Token 받기 + // 2. Access Token을 이용해서 사용자 제공정보 가져오기 + OAuthLogin oauthLogin = new OAuthLogin(oauthVO, deptJsessionId); + + OAuthUniversalUser oauthUser = oauthLogin.getUserProfile(code); // 1,2번 동시 + log.debug("Profile ===>>" + oauthUser); + + String loginResult = loginService.loginOauth(req, oauthUser.getUid(), deptJsessionId); + + // oAuth를 통한 SNS연동이 실패한 경우 + if(oauthUser == null || !oauthUser.isValid()) { + model.addAttribute("message", "먼저 회원가입하신 후, 이용하여 주시기 바랍니다."); + redirectUrl = NlibProperty.getString("member.new.url"); // "/member/insertMemberInfoForm.do" + } + // 정상 SNS 연동 로그인 + else if(oauthUser.isValid() && loginResult == null) { + // 세션에 설정된 redirect 주소 확인 + model.addAttribute("message", "정상적으로 로그인되었습니다."); + String deptHomeUrl = (String)session.getAttribute("deptHomeUrl"); + redirectUrl = deptHomeUrl + "/login/loginDeptSSO.do"; + } + // SNS 로그인은 정상적이나, NLIB 시스템에 등록되지 않은 사용자 : 회원가입으로 전환 + else { + model.addAttribute("code", "GONEW"); + model.addAttribute("message", "먼저 회원가입하신 후, 이용 가능합니다. 해당 SNS 계정 정보로 회원가입을 진행하시겠습니까?"); + redirectUrl = loginResult; + } + + return "redirect:" + redirectUrl; + } + /** * 로그인을 처리한다. (스프링 시큐리티 로그인 수행) * @@ -357,6 +530,70 @@ public class LoginController { return "redirect:" + redirectUrl; } + + @RequestMapping("/login/loginDept.do") + public String loginDept( + HttpServletRequest req, + HttpServletResponse res, + HttpSession session, + @RequestParam(required = false) String returnUrl, + ModelMap model) throws Exception { + + String url = req.getRequestURL().toString(); + String deptHomeUrl = url.replaceAll(req.getRequestURI(), "") + req.getContextPath(); + String deptReturnUrl = deptHomeUrl + (StringUtil.isEmpty(returnUrl) ? "/" : returnUrl); + String deptHostName = StringUtil.getHostName(url); + + session.setAttribute("deptHostName", deptHostName); + session.setAttribute("deptReturnUrl", deptReturnUrl); + session.setAttribute("deptHomeUrl", deptHomeUrl); + + log.debug("REQ URL = " + url); + log.debug("deptJsessionId = " + session.getId()); + log.debug("deptHostName = " + deptHostName); + log.debug("deptReturnUrl = " + deptReturnUrl); + log.debug("deptHomeUrl = " + deptHomeUrl); + + String params = "deptJsessionId=" + session.getId() + + "&deptHostName=" + deptHostName + + "&deptHomeUrl=" + StringUtil.encodeBase64(deptHomeUrl) + + "&deptReturnUrl=" + StringUtil.encodeBase64(deptReturnUrl); + + return "redirect:" + NlibProperty.getString("nculture.login.redirect.url") + "?" + params; + } + + @RequestMapping("/login/loginDeptSSO.do") + public String loginDeptSSO( + HttpServletRequest req, + HttpServletResponse res, + HttpSession session, + ModelMap model) throws Exception { + + String redirectUrl = "/index.do"; + + String snsUserId = SessionConfig.getLoginInfo(session.getId()); + String loginResult = loginService.loginDeptSSO(req, snsUserId); + + // oAuth를 통한 SNS연동이 실패한 경우 + if(loginResult == null) { + // 세션에 설정된 redirect 주소 확인 + String deptReturnUrl = (String)session.getAttribute("deptReturnUrl"); + + log.debug("loginDeptSSO > deptReturnUrl = " + deptReturnUrl); + if(StringUtil.isNotEmpty(deptReturnUrl)) { + redirectUrl = deptReturnUrl; + } + } + // SNS 로그인은 정상적이나, NLIB 시스템에 등록되지 않은 사용자 : 회원가입으로 전환 + else { + model.addAttribute("code", "GONEW"); + model.addAttribute("message", "먼저 회원가입하신 후, 이용 가능합니다. 해당 SNS 계정 정보로 회원가입을 진행하시겠습니까?"); + redirectUrl = loginResult; + } + + return "redirect:" + redirectUrl; + + } /** * 로그아웃 후의 처리를 담당한다. 스프링 시큐리티에서 로그아웃이 수행된 후, 호출된다. diff --git a/src/main/java/nlib/util/StringUtil.java b/src/main/java/nlib/util/StringUtil.java index eaf66979..493f07cd 100644 --- a/src/main/java/nlib/util/StringUtil.java +++ b/src/main/java/nlib/util/StringUtil.java @@ -1,13 +1,19 @@ package nlib.util; +import java.net.URL; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.Base64.Decoder; import java.util.Base64.Encoder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Locale; import egovframework.com.utl.fcc.service.EgovStringUtil; +import nlib.user.web.LoginController; /** *
@@ -32,7 +38,9 @@ import egovframework.com.utl.fcc.service.EgovStringUtil;
  *
  */
 public class StringUtil extends EgovStringUtil {
-
+	
+	private static final Logger log = LoggerFactory.getLogger(StringUtil.class);
+	
 	/**
 	 * Null 이거나, 빈문자열(공백 포함)인 경우, true를 리턴한다.
 	 * 
@@ -137,4 +145,31 @@ public class StringUtil extends EgovStringUtil {
 		Decoder decoder = Base64.getDecoder();
 		return new String(decoder.decode(str.getBytes()));
 	}
+	
+	/**
+	 * URL 주소에서 호스트명을 리턴한다.
+	 * 
+	 * 프로토콜://호스트.도메인/URI 에서 호스트명 리턴 
+	 * (ex) https://seoul.nculture.org/abc/def.do  -> seoul 을 리턴한다. 
+	 * 
+	 * @param url
+	 * @return
+	 * @throws Exception
+	 */
+	public static String getHostName(String url) {
+		if(isEmpty(url)) return "";
+		
+		String hostName = "";
+		
+		try {
+			final URL urlObj = new URL(url);
+			hostName = urlObj.getHost();
+			if(isEmpty(hostName)) return "";
+		} catch(Exception e) {
+			log.error("[ERROR] getHostName(..) : " + e.toString());
+			return "";
+		}
+		
+		return (hostName.split("\\."))[0];
+	}
 }
diff --git a/src/main/resources/egovframework/mapper/config/mapper-config.xml b/src/main/resources/egovframework/mapper/config/mapper-config.xml
index 17568b6e..03e9d61a 100644
--- a/src/main/resources/egovframework/mapper/config/mapper-config.xml
+++ b/src/main/resources/egovframework/mapper/config/mapper-config.xml
@@ -12,7 +12,9 @@
     
     
     
-        
+        
+        
+        
     
     
 
\ 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..5b325e2a
--- /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}
+		    ,'Y'
+		    ,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..81163423
--- /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 cb6038af..12ca478f 100644
--- a/src/main/resources/nlib/nlib.properties
+++ b/src/main/resources/nlib/nlib.properties
@@ -98,3 +98,20 @@ oauth2.client.provider.naver.user-name-attribute = response
 # \uc190\ub2d8\uc815\ubcf4
 #----------------------------------------
 guest.userid = GUEST
+#----------------------------------------
+# \ub85c\uadf8\uc778/\ud68c\uc6d0\uac00\uc785\uad00\ub828 URL \uc815\ubcf4 
+#----------------------------------------
+member.new.url = /member/insertMemberInfoForm.do
+member.login.url = /member/insertMemberInfoForm.do
+# \uc9c0\ubc29\ubb38\ud654\uc6d0\uc5d0\uc11c \uc811\uc18d\uc2dc \ub9ac\ub2e4\uc774\ub809\ud2b8\ub420 URL \uc815\ubcf4 
+nculture.login.redirect.url = http://nlib.nculture.org/nlib/login/loginForm.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
diff --git a/src/main/webapp/WEB-INF/jsp/nlib/login/loginForm.jsp b/src/main/webapp/WEB-INF/jsp/nlib/login/loginForm.jsp
index 6790ee2e..8281b9e7 100644
--- a/src/main/webapp/WEB-INF/jsp/nlib/login/loginForm.jsp
+++ b/src/main/webapp/WEB-INF/jsp/nlib/login/loginForm.jsp
@@ -49,6 +49,13 @@
 
 
 
+ +error : ${error } + 
+message : ${message } + 

+ @@ -60,5 +67,10 @@ +------------------- +" /> +_______________ + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/tiles/inc/header.jsp b/src/main/webapp/WEB-INF/tiles/inc/header.jsp index 62502593..34168e53 100644 --- a/src/main/webapp/WEB-INF/tiles/inc/header.jsp +++ b/src/main/webapp/WEB-INF/tiles/inc/header.jsp @@ -11,7 +11,6 @@
  • 개인정보처리방침
  • 이용약관
  • -
  • 로그인
  • 로그인
  • @@ -26,8 +25,8 @@
  • - - + + ${userName}님 (${userId}) diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 7c82d6bc..29244d90 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -45,6 +45,11 @@ org.springframework.web.context.ContextLoaderListener + + + + org.springframework.web.context.ContextLoaderListener + action diff --git a/src/main/webapp/homes/mapo.jsp b/src/main/webapp/homes/mapo.jsp new file mode 100644 index 00000000..a7a218a0 --- /dev/null +++ b/src/main/webapp/homes/mapo.jsp @@ -0,0 +1,45 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> + + + + + + +마포 문화원 + + + + 

    + +

    마포 문화원

    + + 

    + +JSESSIONID = <%=session.getId() %> + + 

    + +

    로그인

    +로그인 + + 

    + +

    로그인이 필요한 화면 링크

    +프로퍼티갱신 + + 

    + + + + + diff --git a/src/main/webapp/homes/seoul.jsp b/src/main/webapp/homes/seoul.jsp new file mode 100644 index 00000000..6d88b279 --- /dev/null +++ b/src/main/webapp/homes/seoul.jsp @@ -0,0 +1,51 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> + + + + + +서울 문화원 + + + + 

    + +

    서울 문화원

    + + + 

    + +JSESSIONID = <%=session.getId() %> + + 

    + +

    로그인

    +로그인 + + 

    + +

    로그인이 필요한 화면 링크

    +프로퍼티갱신 + +<% +String coutTest = "서울특별시 마포구 "; +%> +" />
    +" /> + + 

    + + + + + diff --git a/src/main/webapp/login/index.jsp b/src/main/webapp/login/index.jsp index a8c362b1..1d3f2449 100644 --- a/src/main/webapp/login/index.jsp +++ b/src/main/webapp/login/index.jsp @@ -1,2 +1,4 @@ <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> - \ No newline at end of file + + +hello \ No newline at end of file