| 카카오톡 간편로그인
과정
Login.html
prompt=login 파라미터는 자동로그인X, 항상 로그인해야함
<div id = "kakao_div">
<img id="kakaoLoginBtn"src="/image/login/kakao.png" alt="" onclick="location.href='https://kauth.kakao.com/oauth/authorize?client_id=REST API 키값&prompt=login&redirect_uri=Redirect URL 값&response_type=code'">
</div>
클릭시 카카오톡 로그인페이지로 이동
카카오로그인페이지
카카오톡 로그인을 통해 얻고자 하는것
사용자의 프로필사진, 닉네님, 이메일 정보
프로세스
1. 사용자가 아이디 비번치고 로그인하면 그 정보가 카카오서버로 바로 전송(개발자는 사용자의 아이디 비밀번호를 알 수 없음)
2. 사용자가 로그인을 성공하면 카카오톡 서버에서 인가코드를 Redirect URI에 전달
3. 개발자는 인가코드를 가지고 카카오서버에 전송하면 사용자의 정보를 넘겨줌
4.카카오 서버가 전달해준 데이터, 여기에서는 id값을 받아서 개발자의 DB에 조회
5.db에 id 값이 존재하면 로그인하듯 진행
6.db에 id 값이 존재하지않으면 Db에 데이터 등록 후 -> 로그인하듯 진행
PageController
@Controller
@RequestMapping("")
@RequiredArgsConstructor
public class PageController {
private final KakaoLoginService kakaoLoginService;
@GetMapping("kakaoLogin")
public String kakao(HttpServletRequest httpServletRequest, ModelMap map,@RequestParam(value = "code", required = false) String code){
HttpSession session = httpServletRequest.getSession();
HashMap<String, Object> userInfo = new HashMap<>();
String tk="";
try{
// System.out.println("1kakaoLoginService.getAccessToken(code);");
tk = kakaoLoginService.getAccessToken(code);
}catch (Exception e){
}
try {
// System.out.println("2 kakaoLoginService.getUserInfo(tk)");
userInfo = kakaoLoginService.getUserInfo(tk);
}
catch (Throwable e) {}
// System.out.println("userId는 " + userInfo.get("userId"));
// System.out.println("memberId는" + userInfo.get("memberId"));
//카카오아디디로 이미 회원가입한 기록이있을경우
if(userInfo.get("userId")!=null){
session.setAttribute("accessToken",tk);
session.setAttribute("loginType","kakao");
session.setAttribute("memberId",userInfo.get("memberId"));
session.setAttribute("userId",userInfo.get("userId"));
session.setAttribute("userName",userInfo.get("userName"));
session.setAttribute("profileImage",userInfo.get("profileImage"));
}
return "redirect:/main";
}
}
IKakaoLoginService(인터페이스)
public interface IKakaoLoginService {
String getAccessToken(String authorize_code) throws Throwable;
public HashMap<String, Object> getUserInfo(String access_Token) throws Throwable;
}
KakaoLoginService
@Service
@RequiredArgsConstructor
public class KakaoLoginService implements IKakaoLoginService {
private final MoneyMemberRepository moneyMemberRepository;
@Override
public String getAccessToken(String authorize_code) throws Exception {
String access_Token = "";
String refresh_Token = "";
String reqURL = "https://kauth.kakao.com/oauth/token";
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// POST 요청을 위해 기본값이 false인 setDoOutput을 true로
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");
sb.append("&client_id=개발자REST_API키"); // REST_API키 본인이 발급받은 key 넣어주기
sb.append("&redirect_uri=리다이렉트주소"); // REDIRECT_URI 본인이 설정한 주소 넣어주기
sb.append("&code=" + authorize_code);
bw.write(sb.toString());
bw.flush();
// 결과 코드가 200이라면 성공
int responseCode = conn.getResponseCode();
// System.out.println("responseCode : " + responseCode);
// 요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
// System.out.println("response body : " + result);
// jackson objectmapper 객체 생성
ObjectMapper objectMapper = new ObjectMapper();
// JSON String -> Map
Map<String, Object> jsonMap = objectMapper.readValue(result, new TypeReference<Map<String, Object>>() {
});
access_Token = jsonMap.get("access_token").toString();
refresh_Token = jsonMap.get("refresh_token").toString();
// System.out.println("access_token : " + access_Token);
// System.out.println("refresh_token : " + refresh_Token);
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
return access_Token;
}
@SuppressWarnings("unchecked")
@Override
public HashMap<String, Object> getUserInfo(String access_Token) throws Throwable {
// 요청하는 클라이언트마다 가진 정보가 다를 수 있기에 HashMap타입으로 선언
HashMap<String, Object> userInfo = new HashMap<String, Object>();
String reqURL = "https://kapi.kakao.com/v2/user/me";
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// 요청에 필요한 Header에 포함될 내용
conn.setRequestProperty("Authorization", "Bearer " + access_Token);
int responseCode = conn.getResponseCode();
// System.out.println("responseCode : " + responseCode);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
// System.out.println("response body : " + result);
// System.out.println("result type" + result.getClass().getName()); // java.lang.String
try {
// jackson objectmapper 객체 생성
ObjectMapper objectMapper = new ObjectMapper();
// JSON String -> Map
Map<String, Object> jsonMap = objectMapper.readValue(result, new TypeReference<Map<String, Object>>() {
});
// System.out.println(jsonMap.get("properties"));
Map<String, Object> properties = (Map<String, Object>) jsonMap.get("properties");
Map<String, Object> kakao_account = (Map<String, Object>) jsonMap.get("kakao_account");
// System.out.println(properties.get("nickname"));
// System.out.println(kakao_account.get("email"));
String nickname = properties.get("nickname").toString();
String userId = jsonMap.get("id").toString(); //카카오로그인회원의 아이디로 쓸 예정
String profileImage = properties.get("profile_image").toString();
Optional<MoneyMember> mem = moneyMemberRepository.findByUserId(userId);
if(mem.isEmpty()){// 아이디가 DB에 존재하지않은 경우(즉, 회원이 아닐경우)
MoneyMember moneyMember = MoneyMember.builder()
.userId(userId)
.userPw(userId+"kakao")
.userName(nickname)
.profileImage(profileImage)
.build();
MoneyMember newMoneyMember = moneyMemberRepository.save(moneyMember);
userInfo.put("memberId",newMoneyMember.getId());
}else{
userInfo.put("memberId",mem.get().getId());
}
userInfo.put("userId",userId);
userInfo.put("userName", nickname);
userInfo.put("profileImage",profileImage);
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return userInfo;
}
}
+ Redirect URI설정
Redirect URI를 위와 같이 정보확인만 따로 하고 페이지이동해주는 페이지로 따로 설정하지않고
main페이지를 Redirect URI 설정하게되면 Main페이지 url에 파라미터로 토큰정보가 붙게됨
그렇게 되면 페이지 이동시 문제가 생김
그래서 Kakao페이지와같은 빈페이지를 따로 만들어줘야함
결과물
❌사진무단도용금지❌
반응형
'웹 개발 > 🍃 SpringBoot' 카테고리의 다른 글
SpringBoot | Thymleaf Fragment(공통영역처리) (0) | 2023.05.26 |
---|---|
SpringBoot | 외부 경로 Resource 접근하기, 이미지 업로드 (0) | 2023.05.25 |
SpringBoot | 로그인,세션등록 (0) | 2023.05.24 |
SpringBoot | 연관관계가 있는 엔티티에서의 CRUD하는법 (0) | 2023.05.21 |
SpringBoot | CRUD 구현 - 글삭제(Delete) (0) | 2023.05.21 |