@Data
public class OAuthToken {
private String access_token;
private String token_type;
private String refresh_token;
private String id_token;
private int expires_in;
private String scope;
private int refresh_token_expires_in;
}
//model담을 객체 만들기
//Gson, Json Simple, ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
try {
OAuthToken oauthToken = objectMapper.readValue(response.getBody(), OAuthToken.class);
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
System.out.println("oauthToekn : " + oauthToken.getAccess_token());
토큰값은 중간에 오류가 생겨서 위에 올린 토큰값이랑 다르게 보일 수도 있습니다. 파싱하면서 model값을 다르게적어서 정말 오래걸렸어요ㅠ_ㅠ
이젠 사용자정보를 가져 올 예정이다
@GetMapping("/auth/kakao/callback")
public @ResponseBody String kakaoCallBack(String code) {
// POST방식으로 key=value 데이터를 요청 (카카오쪽으로)
// Retrofit2
// OkHttp
// RestTemplate
RestTemplate rt = new RestTemplate();
// HttpHeader 오브젝트 생성
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
// HttpBody 오브젝트 생성
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "authorization_code");
params.add("client_id", "c90bfc7a8183f140bc7ddd9aa5ac4134");
params.add("redirect_uri", "http://localhost:8010/auth/kakao/callback");
params.add("code", code);
// HttpHeader와 HttpBody를 하나의 오브젝트에 담기
HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(params, headers);
// Http 요청하기 - Post방식으로 - 그리고 response 변수의 응답 받음.
ResponseEntity<String> response = rt.exchange("https://kauth.kakao.com/oauth/token", // 토큰발급주소
HttpMethod.POST,
kakaoTokenRequest,
String.class);
//Gson, Json Simple, ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
OAuthToken oauthToken = null;
try {
oauthToken = objectMapper.readValue(response.getBody(), OAuthToken.class);
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
//System.out.println("카카오 액세스 토큰 : " + oauthToken.getAccess_token());
RestTemplate rt2 = new RestTemplate();
// HttpHeader 오브젝트 생성
HttpHeaders headers2 = new HttpHeaders();
headers2.add("Authorization", "Bearer "+oauthToken.getAccess_token());
headers2.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
// HttpHeader와 HttpBody를 하나의 오브젝트에 담기
HttpEntity<MultiValueMap<String, String>> kakaoProfileRequest2 = new HttpEntity<>(headers2);
// Http 요청하기 - Post방식으로 - 그리고 response 변수의 응답 받음.
ResponseEntity<String> response2 = rt2.exchange(
"https://kapi.kakao.com/v2/user/me", // 토큰발급주소
HttpMethod.POST,
kakaoProfileRequest2,
String.class);
return response2.getBody(); //회원정보 결과가 담겨서 보여질 것
}
회원정보가 제대로 나온다..🥺 기쁨의 눈물...ㅠㅠㅠㅠ
https://www.jsonschema2pojo.org 들어가서
현재작업 패키지명을 입력해주고 model패키지
model이름을 적어주고 난뒤 Preview 클릭하고 복사한다
;
import lombok.Data;
@Data
public class KakaoProfile {
public Long id;
public String connected_at;
public Properties properties;
public KakaoAccount kakao_account;
@Data
public class Properties {
public String profile_image;
public String thumbnail_image;
}
@Data
public class KakaoAccount {
public Boolean profile_image_needs_agreement;
public Profile profile;
public Boolean has_email;
public Boolean email_needs_agreement;
public Boolean is_email_valid;
public Boolean is_email_verified;
public String email;
@Data
public class Profile {
public String thumbnail_image_url;
public String profile_image_url;
public Boolean is_default_image;
}
}
}
@GetMapping("/auth/kakao/callback")
public @ResponseBody String kakaoCallBack(String code) {
//생략...
ObjectMapper objectMapper2 = new ObjectMapper();
KakaoProfile KakaoProfile = null;
try {
KakaoProfile = objectMapper2.readValue(response2.getBody(), KakaoProfile.class);
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
System.out.println("카카오아이디(번호) : "+kakaoProfile.getId() +
" 카카오 이메일 :" + kakaoProfile.getKakao_account().getEmail());
}
콘솔창에 카카오번호와 이메일을 잘가지고 온다!!!
이제 카카오로 로그인을 할때 이름과 이메일과 비밀번호 기존에 만들었던 User 엔티티랑 비교를 해봤을때
//UserDto 오브젝트 : username, password, email
System.out.println(" 카카오아이디(번호) : "+kakaoProfile.getId());
System.out.println(" 카카오 이메일 :" + kakaoProfile.getKakao_account().getEmail());
System.out.println(" 블로그서버 유저네임 : " + kakaoProfile.getKakao_account().getEmail()+ "_" + kakaoProfile.getId());
System.out.println(" 블로그서버 이메일 : " + kakaoProfile.getKakao_account().getEmail()+ "_" + kakaoProfile.getId());
UUID garbagePassword = UUID.randomUUID(); //랜덤값
System.out.println(" 블로그서버 비밀번호 : " + garbagePassword);
카카오에서 가져온 아이디(번호)와 이메일을 가지고
블로그서버 유저네임과 블로그서버 이메일은 동일하게 설정하고
비밀번호는 가비지패스워드 UUID로 설정해준다.
//생성자주입
private final UserService userService;
//생략...
UserDto userDto = UserDto.builder()
.username( kakaoProfile.getKakao_account().getEmail()+ "_" + kakaoProfile.getId())
.password(garbagePassword.toString())
.email(kakaoProfile.getKakao_account().getEmail())
.build();
userService.join(userDto);
//일단 제대로 나오는지 한번 확인해보기
return "회원가입 완료" ;
제대로 나오는지 return값으로 확인해보기
근데 무조건 회원가입을 하면 안되기 때문에
가입자 혹은 비가입자 체크 해서 처리
username으로 찾기
@Transactional(readOnly = true)
public User findUser(String username) {
User user = userRepository.findByUsername(username).orElseGet(()->{
return new User();
});
return user;
}
userApiController에 있는
principalDetailService 생성자주입이랑
로그인 세션 등록부분을 그대로 들고온다.
//생성자 주입
@Autowired
private PrincipalDetailService principalDetailService;
@GetMapping("/auth/kakao/callback")
public String kakaoCallBack(String code) {
User kakaoUser = User.builder()
.username(kakaoProfile.getKakao_account().getEmail()+ "_" + kakaoProfile.getId())
.password(garbagePassword.toString())
.email(kakaoProfile.getKakao_account().getEmail())
//.oauth("kakao")
.build();
//가입자 혹은 비가입자 체크 해서 처리
User originUser = userService.findUser(kakaoUser.getUsername());
if(originUser.getUsername() == null) {
System.out.println("기존 회원이 아니기에 자동 회원가입을 진행합니다");
System.out.println(kakaoUser.getUsername());
userService.findUser(kakaoUser.getUsername());
}
System.out.println("자동 로그인을 진행합니다.");
// 로그인 처리
//자동로그인 진행
UserDetails userDetail = principalDetailService.loadUserByUsername(kakaoUser.getUsername());
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetail, null, userDetail.getAuthorities());
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
return "redirect:/";
}
kakaoCallBack 메서드 앞에 적은 @ResponseBody를 지워져야 리턴이 제대로 리다이렉트 된다.!
로그인이 제대로 되고
DB에도 제대로 들어간걸 확인할 수 있다.!!!
그리고 회원수정을 들어가보면 설정해놓은 이름으로 제대로 들어갔고
회원수정을 할때 비밀번호는 콘솔창에 나온 비밀번호를 입력해주면 제대로 회원정보도 변경이된다.!!! 😄