Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 파이썬
- spring security
- spring oauth
- MySQL
- 백준 15685
- 백준 16236
- java 기술면접
- 웹어플리케이션 서버
- re.split
- JVM
- 프로래머스
- 백준 파이썬
- java
- 프로그래머스
- with recursive
- JPA
- 백준 17626
- 백준 17779
- Spring
- MSA
- 백준
- Kotlin
- Coroutine
- Spring Boot
- spring cloud
- springboot
- 백준 16235
- 백준 16719
- sql 기술면접
- 백준 19238
Archives
- Today
- Total
시작이 반
[Spring] 2. Oauth 2.0 카카오 로그인 구현 본문
SMALL
로그인이 정상적으로 됐으면 해당 Redirect URI로 code가 넘어옴
@GetMapping("/auth/kakao/callback")
public String kakaoCallback(@RequestParam("code") String code){
OAuthToken oAuthToken = kaKaoApiService.tokenRequest(code); //1.토큰 가져오기
KakaoProfile kakaoProfile = kaKaoApiService.userInfoRequest(oAuthToken); //2.유저정보 가져오기
int idx = kakaoProfile.getKakao_account().getEmail().indexOf("@");
String username = kakaoProfile.getKakao_account().getEmail().substring(0, idx);
System.out.println("유저네임:" + username);
User kakaoUser = User.builder()
.username(username)
.password(kakaoProfile.getKakao_account().getEmail() + kakaoProfile.getId())
.oauth("kakao")
.build();
//3.회원가입, 로그인
userService.join(kakaoUser);
return "redirect:/";
}
넘어온 코드를 사용하여 Token을 만들어야함
1. 토큰 가져오기
RestTmeplate을 사용하여 요청한다.
public OAuthToken tokenRequest(String code) {
//POST방식으로 데이터 요청
RestTemplate restTemplate = new RestTemplate();
//HttpHeader
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
//HttpBody
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("client_id", clientId); //clientId 는 프로퍼티에 정의해놨음
body.add("redirect_uri", "http://localhost:8080/auth/kakao/callback");
body.add("code", code);
//HttpHeader와 HttpBody 담기기
HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(body, headers); // params : body
return restTemplate.exchange("https://kauth.kakao.com/oauth/token", HttpMethod.POST, kakaoTokenRequest, OAuthToken.class).getBody();
}
package Social.Sociallogin.dto;
import lombok.Data;
@Data
public class OAuthToken {
private String access_token;
private String token_type;
private String refresh_token;
private int expires_in;
private String scope;
private int refresh_token_expires_in;
}
2. 유저정보 가져오기
토큰정보를 받아오면 해당 토큰을 사용하여 유저 정보를 가져올 수 있다.
public KakaoProfile userInfoRequest(OAuthToken oAuthToken) {
///유저정보 요청
RestTemplate restTemplate = new RestTemplate();
//HttpHeader
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + oAuthToken.getAccess_token());
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
//HttpHeader와 HttpBody 담기기
HttpEntity<MultiValueMap<String, String>> kakaoProfileRequest = new HttpEntity<>(headers);
return restTemplate.exchange("https://kapi.kakao.com/v2/user/me", HttpMethod.POST, kakaoProfileRequest, KakaoProfile.class).getBody();
}
package Social.Sociallogin.dto;
import lombok.Data;
@Data
public class KakaoProfile {
public Integer id;
public String connected_at;
public Properties properties;
public KakaoAccount kakao_account;
@Data
public class Properties {
public String nickname;
public String profile_image;
public String thumbnail_image;
}
@Data
public class KakaoAccount {
public Boolean profile_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 nickname;
public String thumbnail_image_url;
public String profile_image_url;
}
}
}
3. 회원가입, 로그인
유저정보를 가져왔으면 DB에 정보가 없으면 회원가입을 시킨다.
회원가입의 아이디는 주소의 @이를 기준으로 잘랐으며
비밀번호는 이메일 + 고유id를 사용하여 만들었다..
이후에 Authentication으로 등록을 해준다.
int idx = kakaoProfile.getKakao_account().getEmail().indexOf("@");
String username = kakaoProfile.getKakao_account().getEmail().substring(0, idx);
User kakaoUser = User.builder()
.username(username)
.password(kakaoProfile.getKakao_account().getEmail() + kakaoProfile.getId())
.oauth("kakao")
.build();
//회원가입, 로그인
userService.join(kakaoUser);
package Social.Sociallogin.service;
import Social.Sociallogin.domain.User;
import Social.Sociallogin.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Service
public class UserService {
private UserRepository userRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;
private AuthenticationManager authenticationManager;
@Autowired
public UserService(UserRepository userRepository, BCryptPasswordEncoder bCryptPasswordEncoder, AuthenticationManager authenticationManager) {
this.userRepository = userRepository;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.authenticationManager = authenticationManager;
}
@Transactional
public void join(User user){
if(user.getOauth() != null){//카카오 로그인
String rawPassword = user.getPassword();
if(!kakaovalidateDuplicateUser(user).isPresent()){
//회원가입
String encPassword = bCryptPasswordEncoder.encode(user.getPassword());
user.setPassword(encPassword);
userRepository.save(user);
}
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), rawPassword));
SecurityContextHolder.getContext().setAuthentication(authentication);
}else{
validateDuplicateUser(user);
String encPassword = bCryptPasswordEncoder.encode(user.getPassword());
user.setPassword(encPassword);
userRepository.save(user);
}
}
@Transactional(readOnly = true)
public void validateDuplicateUser(User user){
userRepository.findByUsername(user.getUsername())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원");
});
}
@Transactional(readOnly = true)
public Optional<User> kakaovalidateDuplicateUser(User user){
return userRepository.findByUsername(user.getUsername());
}
}
LIST
'Programming > Spring' 카테고리의 다른 글
Thymeleaf 자바스크립트 함수 사용 (0) | 2021.02.21 |
---|---|
[Spring] 스프링 시큐리티 Authentication 바꿔주기 (0) | 2021.02.17 |
[Spring] 1. Oauth 2.0 카카오 로그인 세팅 (0) | 2021.02.17 |
[Spring] 0. OAuth2.0 카카오 과정 (0) | 2021.02.15 |
[Spring] Thymeleaf에서 세션 확인 (th에서 authentication사용하기) (0) | 2021.02.14 |