카카오, 구글은 자바스크립트 로그인
SNS api 설정 및 참조
https://tyrannocoding.tistory.com/51
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ page import="java.net.URLEncoder" %> <%@ page import="java.security.SecureRandom" %> <%@ page import="java.math.BigInteger" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ include file="../common/header.jsp" %> <% // 네이버 로그인 String clientId = "iDRiqlC1V1cqQU1U9LatV";//애플리케이션 클라이언트 아이디값"; String redirectURI = URLEncoder.encode("http://localhost:8000/sns/naverCallback", "UTF-8"); SecureRandom random = new SecureRandom(); String state = new BigInteger(130, random).toString(); String apiURL = "https://nid.naver.com/oauth2.0/authorize?response_type=code"; apiURL += "&client_id=" + clientId; apiURL += "&redirect_uri=" + redirectURI; apiURL += "&state=" + state; session.setAttribute("state", state); //END 네이버 로그인 %> <link rel="stylesheet" href="/css/loginStyle.css"> <!-- 카카오 스크립트 --> <script src="https://developers.kakao.com/sdk/js/kakao.js"></script> <div class="login__wrapper" style="margin-top: 115px; height: 734px;"> <div class="container"> <div class="panel-body"> <div class="mb-3"> <label for="username">아이디(Email)</label> <div class="input-group"> <input type="text" class="form-control" id="username" placeholder="" name="user-id" required="required"> <div class="invalid-feedback" style="width: 100%;">Your username is required.</div> </div> </div> <div class="mb-3"> <label for="username">비밀번호</label> <div class="input-group"> <input type="password" class="form-control" id="pw" placeholder="" name="user-id" required="required"> <div class="invalid-feedback" style="width: 100%;">Your username is required.</div> </div> </div> </div> <hr/> <button id="login-btn" class="btn btn-primary btn-lg" style="width: 100%">로그인</button> <hr/> <div class="sign__container" style="left: -35px;position: relative;"> <div class="other_id_join"> <a class="naver" href="<%=apiURL%>" ><span class="sns_icon">네이버로 로그인</span></a> <a class="kakao" href="#" onclick="kakaoLogin();"><span class="sns_icon">카카오톡으로 로그인</span></a> <a class="google" id="GgCustomLogin" href="javascript:void(0);" ><span class="sns_icon">구글로 로그인</span></a> </div> <div class="sign__box" style="margin-top:20px; width: 490px "> <span>아직 회원이 아니신가요?</span> <a href="/user/join">회원가입</a> </div> </div> </div> </div> <script src="/js/login.js"></script> <script> let naverError='${naverError}'; if(naverError!=""){ alert(naverError); } Kakao.init('34ddf13d2cd34ca551657751f26ba8cc8'); //발급받은 키 중 javascript키를 사용해준다. console.log(Kakao.isInitialized()); // sdk초기화여부판단 //카카오로그인 function kakaoLogin() { Kakao.Auth.login({ success: function (response) { Kakao.API.request({ url: '/v2/user/me', success: function (response) { console.dir(response); console.log(response.kakao_account.email); snsLoginProcess("kakao", response.id ,response.kakao_account.email,response.kakao_account.profile.nickname); }, fail: function (error) { console.log(error) }, }) }, fail: function (error) { console.log(error) }, }); return false; } function snsLoginProcess(type,id,email,nickname){ console.log(type, id, email , nickname); $.ajax({ url:"/sns/snsLoginProcess", type:"post", data:{ 'snsType':type, 'snsId':id, 'email':email, 'nickname' :nickname }, success:function(resultMap){ //console.log("ok"); console.log(resultMap); if(resultMap.status=="success"){ location.href="/"; }else if(resultMap.status=="NoSuchElementException"){ alert("등록되지 않은 회원입니다."); }else if(resultMap.status=="error"){ alert("선택 제공 항목 카카오계정(이메일)을 선택해 주세요."); } }, error:function(result){ console.log(result); alert("카카오 로그인 오류"); } }); kakaoLogout(); } //카카오로그아웃 function kakaoLogout() { if (Kakao.Auth.getAccessToken()) { Kakao.API.request({ url: '/v1/user/unlink', success: function (response) { console.log(response) }, fail: function (error) { console.log(error) }, }) Kakao.Auth.setAccessToken(undefined) } } </script> <!-- 구글 api 사용을 위한 스크립트 --> <script> //처음 실행하는 함수 function init() { gapi.load('auth2', function() { gapi.auth2.init(); options = new gapi.auth2.SigninOptionsBuilder(); options.setPrompt('select_account'); // 추가는 Oauth 승인 권한 추가 후 띄어쓰기 기준으로 추가 options.setScope('email profile openid https://www.googleapis.com/auth/user.birthday.read'); // 인스턴스의 함수 호출 - element에 로그인 기능 추가 // GgCustomLogin은 li태그안에 있는 ID, 위에 설정한 options와 아래 성공,실패시 실행하는 함수들 gapi.auth2.getAuthInstance().attachClickHandler('GgCustomLogin', options, onSignIn, onSignInFailure); }) } function onSignIn(googleUser) { var access_token = googleUser.getAuthResponse().access_token $.ajax({ // people api를 이용하여 프로필 및 생년월일에 대한 선택동의후 가져온다. url: 'https://people.googleapis.com/v1/people/me' // key에 자신의 API 키를 넣습니다. , data: {personFields:'birthdays', key:'AIzaSyCC8gzwojhQfclUfYk4VbdfIQ_pzQ1Je0Ea', 'access_token': access_token} , method:'GET' }) .done(function(e){ //프로필을 가져온다. let profile = googleUser.getBasicProfile(); console.dir(profile) let type="google"; let id= profile.sT; let email=profile.Tt; let nickname= profile.Re; snsLoginProcess(type, id, email,nickname) }) .fail(function(e){ console.log(e); }) } function onSignInFailure(t){ console.log(t); } </script> <!-- 구글 api 사용을 위한 스크립트 --> <script src="https://apis.google.com/js/platform.js?onload=init" async defer></script> <%@ include file="../common/footer.jsp" %>
SNSController
import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSession; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; 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.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.fasterxml.jackson.core.JsonProcessingException; import com.project.localbatter.dto.UserDTO; import com.project.localbatter.entity.UserEntity; import com.project.localbatter.repositories.UserRepository; import com.project.localbatter.services.UserService; import lombok.RequiredArgsConstructor; @Controller @RequiredArgsConstructor public class SNSController { private final static Logger log = LogManager.getLogger(); private final UserRepository userRepository; private final UserService userService; @RequestMapping("/naver") public String naver() { return "/sns/naver"; } @RequestMapping("/facebook") public String facebook() { return "/sns/facebook"; } @RequestMapping("/sns/naverCallback") public String callback() { return "/sns/naverCallback"; } @GetMapping("/sns/naverLoginProcess") public String naverLoginProcess(HttpSession session, UserDTO vo, RedirectAttributes rttr) { Object snsObjet=session.getAttribute("snsObjet"); if(snsObjet==null) return "redirect:/"; String snsType=""; String snsId=""; String email=""; String nickname=""; String phoneNum=""; try { JSONParser jsonParser = new JSONParser(); JSONObject jsonObject = (JSONObject) jsonParser.parse(snsObjet.toString()); snsType="naver"; snsId=jsonObject.get("id").toString(); email=jsonObject.get("email").toString(); nickname=jsonObject.get("nickname").toString(); phoneNum=jsonObject.get("mobile").toString(); log.info(" 등록할 정보 : {} , {} , {}, {} , {} " , snsType ,snsId ,email , nickname, phoneNum); UserEntity userEntity = userRepository.findByUsername(email).get(); Authentication authentication = new UsernamePasswordAuthenticationToken(userEntity, userEntity.getPassword(), userEntity.getAuthorities()); SecurityContext securityContext = SecurityContextHolder.getContext(); securityContext.setAuthentication(authentication); session.setAttribute("g_user", userEntity); session.removeAttribute("snsObjet"); } catch (Exception e) { //rttr.addFlashAttribute("naverError","등록되지 않은 회원입니다."); //등록된 이메일 존재하지 않을 경우 회원가입 처리 후 로그인 vo.setUsername(email); vo.setNickname(nickname); vo.setPhone(phoneNum); vo.setSnsType(snsType); vo.setSnsId(snsId); vo.setPassword(snsType+email+snsId);//임의 비밀번호 userService.userSave(vo); //로그인 처리 UserEntity userEntity = userRepository.findByUsername(email).get(); Authentication authentication = new UsernamePasswordAuthenticationToken(userEntity, userEntity.getPassword(), userEntity.getAuthorities()); SecurityContext securityContext = SecurityContextHolder.getContext(); securityContext.setAuthentication(authentication); session.setAttribute("g_user", userEntity); session.removeAttribute("snsObjet"); } return "redirect:/"; } //구글, 카카오 // REST API의 조건(쿠키 기반의 세션 처리)에는 더 이상 CSRF이 관련이 없으므로 이러한 API는 CSRF 공격을 받을 가능성이 존재하지 않는다. @PostMapping("/sns/snsLoginProcess") @ResponseBody public Map<String, Object> snsLoginProcess(HttpSession session, @RequestParam Map<String, String> param, UserDTO vo) throws JsonProcessingException{ Map<String, Object> resultMap=new HashMap<String, Object>(); resultMap.put("status", "error"); log.info(" param : {} " , param.toString()); if(param.get("email")!=null && !param.get("email").equals("") && param.get("snsId")!=null && !param.get("snsId").equals("") ) { try { //등록된 이메일 존재시 로그인 처리 UserEntity userEntity = userRepository.findByUsername(param.get("email")).get(); Authentication authentication = new UsernamePasswordAuthenticationToken(userEntity, userEntity.getPassword(), userEntity.getAuthorities()); SecurityContext securityContext = SecurityContextHolder.getContext(); securityContext.setAuthentication(authentication); session.setAttribute("g_user", userEntity); resultMap.put("status", "success"); }catch (Exception e) { try { //등록된 이메일 존재하지 않을 경우 회원가입 처리 후 로그인 vo.setUsername(param.get("email")); vo.setNickname(param.get("nickname")); vo.setPhone(param.get("phoneNum")); vo.setSnsType(param.get("snsType")); vo.setSnsId(param.get("snsId")); vo.setPassword(param.get("snsType")+param.get("email")+param.get("snsId"));//임의 비밀번호 userService.userSave(vo); //로그인 처리 UserEntity userEntity = userRepository.findByUsername(param.get("email")).get(); Authentication authentication = new UsernamePasswordAuthenticationToken(userEntity, userEntity.getPassword(), userEntity.getAuthorities()); SecurityContext securityContext = SecurityContextHolder.getContext(); securityContext.setAuthentication(authentication); session.setAttribute("g_user", userEntity); resultMap.put("status", "success"); }catch (Exception e2) { resultMap.put("status", "error"); } } } return resultMap; } }
네이버 - 자바로 개발
pom.xml
<dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.1</version> </dependency>
NaverApiExamMemberProfile
//네이버 API 예제 - 회원프로필 조회 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Service; import com.project.localbatter.components.GenerateFile; import com.project.localbatter.components.PagingUtil; import com.project.localbatter.entity.UserEntity; import com.project.localbatter.repositories.ProfileRepository; import com.project.localbatter.repositories.UserRepository; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @Configuration public class NaverApiExamMemberProfile { private final static Logger log = LogManager.getLogger(); public String getInfo(String jsonData, HttpServletRequest request) { JSONParser jsonParser = new JSONParser(); try { JSONObject jsonObject = (JSONObject) jsonParser.parse(jsonData); //System.out.println("\n\n\n jsonObject : " +jsonObject.toString()); //System.out.println("\n\n\n access_token : " +jsonObject.get("access_token")); String token=(String)jsonObject.get("access_token"); String header = "Bearer " + token; // Bearer 다음에 공백 추가 String apiURL = "https://openapi.naver.com/v1/nid/me"; Map<String, String> requestHeaders = new HashMap<>(); requestHeaders.put("Authorization", header); String responseBody = get(apiURL,requestHeaders); log.info("responseBody : {} ", responseBody); JSONParser jsonParser2 = new JSONParser(); JSONObject resObj = (JSONObject) jsonParser2.parse(responseBody); String obj1=resObj.get("response").toString(); log.info("** obj1 : {}" ,obj1); JSONParser jsonParser3 = new JSONParser(); JSONObject resObj2 = (JSONObject) jsonParser3.parse(obj1); String email=resObj2.get("email").toString(); System.out.println("** email : " +email); //return email; return resObj2.toString(); } catch (ParseException e) { e.printStackTrace(); return null; } } private static String get(String apiUrl, Map<String, String> requestHeaders){ HttpURLConnection con = connect(apiUrl); try { con.setRequestMethod("GET"); for(Map.Entry<String, String> header :requestHeaders.entrySet()) { con.setRequestProperty(header.getKey(), header.getValue()); } int responseCode = con.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출 return readBody(con.getInputStream()); } else { // 에러 발생 return readBody(con.getErrorStream()); } } catch (IOException e) { throw new RuntimeException("API 요청과 응답 실패", e); } finally { con.disconnect(); } } private static HttpURLConnection connect(String apiUrl){ try { URL url = new URL(apiUrl); return (HttpURLConnection)url.openConnection(); } catch (MalformedURLException e) { throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e); } catch (IOException e) { throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e); } } private static String readBody(InputStream body){ InputStreamReader streamReader = new InputStreamReader(body); try (BufferedReader lineReader = new BufferedReader(streamReader)) { StringBuilder responseBody = new StringBuilder(); String line; while ((line = lineReader.readLine()) != null) { responseBody.append(line); } return responseBody.toString(); } catch (IOException e) { throw new RuntimeException("API 응답을 읽는데 실패했습니다.", e); } } }
naver.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.net.URLEncoder" %> <%@ page import="java.security.SecureRandom" %> <%@ page import="java.math.BigInteger" %> <!doctype html> <html lang="ko"> <head> <meta charset="utf-8"> <title>네이버 로그인</title> <script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script> <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script> </head> <body> <!-- 네이버아이디로로그인 버튼 노출 영역 --> <div id="naver_id_login"></div> <!-- //네이버아이디로로그인 버튼 노출 영역 --> <script type="text/javascript"> var naver_id_login = new naver_id_login("iDRiqlC13V1cqQUU29LatV", "http://localhost:8000/sns/naverCallback"); var state = naver_id_login.getUniqState(); naver_id_login.setButton("white", 2,40); naver_id_login.setDomain("YOUR_SERVICE_URL"); naver_id_login.setState(state); naver_id_login.setPopup(); naver_id_login.init_naver_id_login(); </script> </html>
naverCallback.jsp
<%@page import="com.project.localbatter.config.NaverApiExamMemberProfile"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.net.URLEncoder" %> <%@ page import="java.net.URL" %> <%@ page import="java.net.HttpURLConnection" %> <%@ page import="java.io.BufferedReader" %> <%@ page import="java.io.InputStreamReader" %> <html> <head> <title>네이버로그인</title> </head> <body> <% String clientId = "iDRiqlC1V1cqQ2UU9LatV";//애플리케이션 클라이언트 아이디값"; String clientSecret = "ToHePA4_og";//애플리케이션 클라이언트 시크릿값"; String code = request.getParameter("code"); String state = request.getParameter("state"); String redirectURI = URLEncoder.encode("http://localhost:8000/sns/naverCallback", "UTF-8"); String apiURL; apiURL = "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&"; apiURL += "client_id=" + clientId; apiURL += "&client_secret=" + clientSecret; apiURL += "&redirect_uri=" + redirectURI; apiURL += "&code=" + code; apiURL += "&state=" + state; String access_token = ""; String refresh_token = ""; System.out.println("apiURL="+apiURL); try { URL url = new URL(apiURL); HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setRequestMethod("GET"); int responseCode = con.getResponseCode(); BufferedReader br; System.out.print("responseCode="+responseCode); if(responseCode==200) { // 정상 호출 br = new BufferedReader(new InputStreamReader(con.getInputStream())); } else { // 에러 발생 br = new BufferedReader(new InputStreamReader(con.getErrorStream())); } String inputLine; StringBuffer res = new StringBuffer(); while ((inputLine = br.readLine()) != null) { res.append(inputLine); } br.close(); if(responseCode==200) { out.print("로그인 토큰"); out.println(res.toString()); String result=new NaverApiExamMemberProfile().getInfo(res.toString(), request); out.println("<br><br>로그인 성공 : "+ result); if(result!=null && !result.equals("")){ session.setAttribute("snsObjet", result); response.sendRedirect("/sns/naverLoginProcess"); }else{ out.println("로그인 실패"); } } } catch (Exception e) { System.out.println(e); } %> </body> </html>
댓글 ( 4)
댓글 남기기