From f9cceb2a802dae49572e1ecafad1c93d411e67ed Mon Sep 17 00:00:00 2001 From: KNKIM Date: Mon, 23 Aug 2021 16:17:56 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8B=A4=EC=A4=91=20=ED=98=B8=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=84=B8=EC=85=98=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ext/oauth/service/OAuthLogin.java | 30 ++ .../ext/oauth/service/OAuthUniversalUser.java | 9 + .../java/nlib/cmm/service/NlibProperty.java | 5 +- .../java/nlib/cmm/session/SessionConfig.java | 72 ++++ .../nlib/security/SpringSecurityConfig.java | 2 +- .../java/nlib/user/service/LoginService.java | 6 +- .../user/service/impl/LoginServiceImpl.java | 49 ++- .../java/nlib/user/web/LoginController.java | 391 +++++++++++++----- src/main/java/nlib/util/StringUtil.java | 2 +- src/main/resources/nlib/nlib.properties | 4 +- src/main/webapp/WEB-INF/web.xml | 5 + src/main/webapp/homes/seoul.jsp | 1 - 12 files changed, 474 insertions(+), 102 deletions(-) create mode 100644 src/main/java/nlib/cmm/session/SessionConfig.java 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/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/SpringSecurityConfig.java b/src/main/java/nlib/security/SpringSecurityConfig.java index 0e796bdb..8a6eb302 100644 --- a/src/main/java/nlib/security/SpringSecurityConfig.java +++ b/src/main/java/nlib/security/SpringSecurityConfig.java @@ -54,7 +54,6 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { .antMatchers("/js/**") .antMatchers("/temp/**") .antMatchers("/favicon/**") - .antMatchers("/homes/**") ; } @@ -85,6 +84,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { .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 87c5f80a..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(HttpServletRequest req, String snsUserId); + 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/impl/LoginServiceImpl.java b/src/main/java/nlib/user/service/impl/LoginServiceImpl.java index 3305d0e7..cd99ff29 100644 --- a/src/main/java/nlib/user/service/impl/LoginServiceImpl.java +++ b/src/main/java/nlib/user/service/impl/LoginServiceImpl.java @@ -13,9 +13,11 @@ 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; @@ -133,7 +135,48 @@ public class LoginServiceImpl implements LoginService * null이 아닌 경우, REDIRECT되어야 하는 URL(오류 코드 포함) * */ - public String loginOauth(HttpServletRequest req, String snsUserId) { + 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"; @@ -179,6 +222,8 @@ public class LoginServiceImpl implements LoginService return null; } + + /* SNS 연동 SSO를 통한 로그인 처리한다. * @@ -186,7 +231,7 @@ public class LoginServiceImpl implements LoginService * null이 아닌 경우, REDIRECT되어야 하는 URL(오류 코드 포함) * */ - public String loginSSO(HttpServletRequest req, String snsUserId) { + public String loginDept(HttpServletRequest req, String snsUserId) { // SNS 연동 사용자UID로 사용자정보 조회 if(StringUtil.isEmpty(snsUserId)) return "/login/loginForm.do?error=req-sns-sso"; diff --git a/src/main/java/nlib/user/web/LoginController.java b/src/main/java/nlib/user/web/LoginController.java index 8b93be46..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,48 +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.servlet.mvc.support.RedirectAttributes; -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 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; +import nlib.cmm.session.SessionConfig; import nlib.user.service.LoginService; import nlib.util.StringUtil; @@ -125,32 +101,82 @@ public class LoginController { @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, deptJsessionId); + log.debug("naverLogin.getOAuthURL() = "+naverLogin.getOAuthURL()); + model.addAttribute("naverUrl", naverLogin.getOAuthURL()); + + OAuthLogin googleLogin = new OAuthLogin(googleAuthVO, deptJsessionId); + log.debug("googleLogin.getOAuthURL() = "+googleLogin.getOAuthURL()); + model.addAttribute("googleUrl", googleLogin.getOAuthURL()); + + 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)); - // 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.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) { @@ -184,53 +210,70 @@ public class LoginController { // 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, 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 loginResult = loginService.loginOauth(req, oauthUser.getUid()); - - // 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; - } - 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 }) @@ -334,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; + } + /** * 로그인을 처리한다. (스프링 시큐리티 로그인 수행) * @@ -371,23 +536,63 @@ public class LoginController { HttpServletRequest req, HttpServletResponse res, HttpSession session, - RedirectAttributes redirectAttrs, + @RequestParam(required = false) String returnUrl, ModelMap model) throws Exception { String url = req.getRequestURL().toString(); - String deptReturnUrl = url.replaceAll(req.getRequestURI(), "/"); + 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); - redirectAttrs.addFlashAttribute("deptJsessionId", session.getId()); - redirectAttrs.addFlashAttribute("deptHostName", deptHostName); - redirectAttrs.addFlashAttribute("deptReturnUrl", deptReturnUrl); + 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; - return "redirect:/login/loginForm.do"; } /** diff --git a/src/main/java/nlib/util/StringUtil.java b/src/main/java/nlib/util/StringUtil.java index e9c3bc50..493f07cd 100644 --- a/src/main/java/nlib/util/StringUtil.java +++ b/src/main/java/nlib/util/StringUtil.java @@ -156,7 +156,7 @@ public class StringUtil extends EgovStringUtil { * @return * @throws Exception */ - public static String getHostName(String url) throws Exception { + public static String getHostName(String url) { if(isEmpty(url)) return ""; String hostName = ""; diff --git a/src/main/resources/nlib/nlib.properties b/src/main/resources/nlib/nlib.properties index 2e5c1f71..ae930a98 100644 --- a/src/main/resources/nlib/nlib.properties +++ b/src/main/resources/nlib/nlib.properties @@ -91,13 +91,13 @@ 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 - +# \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 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/seoul.jsp b/src/main/webapp/homes/seoul.jsp index d351a4f0..6d88b279 100644 --- a/src/main/webapp/homes/seoul.jsp +++ b/src/main/webapp/homes/seoul.jsp @@ -4,7 +4,6 @@ <%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> -