카카오, 구글은 자바스크립트 로그인
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)
댓글 남기기