2024. 5. 14. 09:56ㆍFull Stack Course 풀스택과정/SPRING
배울내용:
OAuth2 실행테스트
OAuth2 카카오 로그인
스프링부트 OAuth2
SpringBoot OAuth2
카카오 로그인 만들기
kakao 로그인
카카오 로그인 연동
카카오 로그인 DB저장
카카오 로그인후 메인화면이동
OAuth 뷰 구성
지난 1편에서 부터 이어집니다
https://sarimus.tistory.com/130
SpringBoot - OAuth2 로 카카오 로그인
배울내용:OAuth2 실행테스트OAuth2 구글 로그인스프링부트 OAuth2 SpringBoot OAuth2카카오 로그인 만들기kakao 로그인 카카오 로그인 연동액세스 토큰 만들기인증 관련 설정값OAuth 뷰 구성 이번 포스팅
sarimus.tistory.com
먼저 email은 kakao developers 에 동의항목에 보면 선택할수가없다 !
이메일을 로그인 시, 필수 동의로 설정하려면 비즈앱 전환이 필요합니다.
디벨로퍼스 앱에 사업자 정보를 입력하고 비즈 앱으로 설정해야한다 .
비즈 앱으로 설정할 경우, 개인정보 항목 중 이메일을 '연결 시 필수’로 설정할 수 있고 같은 사업자 번호로 인증된 프로필(플러스친구)과 연결할 수 있으며 서브 도메인, 친구 API등 추가 권한을 신청할 수 있습니다.
비즈 앱은 아래의 경로에서 진행할 수 있습니다.
[내 애플리케이션] > [앱 설정] > [비즈니스] > [비즈 앱 정보 ]> [사업자 정보 등록]
비즈 앱에 관한 정보는 가이드에서도 확인하실 수 있다.
그렇게 설정하면 아래처럼 선택할수가 있다
이후에 이전에 써놨던 SecurityConfig 에 있는
successHandler
성공핸들러에 보면 아래 처럼 id 값만 받아왔다
@Bean
public AuthenticationSuccessHandler successHandler() {
return ((request, response, authentication) -> {
DefaultOAuth2User defaultOAuth2User = (DefaultOAuth2User) authentication.getPrincipal();
String id = defaultOAuth2User.getAttributes().get("id").toString();
// 이메일 주소를 찾았을 때만 값을 추출하여 사용
if (matcher.find()) {
email = matcher.group();
}
String body = """
{"id":"%s"}
""".formatted(id);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
PrintWriter writer = response.getWriter();
writer.println(body);
writer.flush();
});
}
그러면 여기서 email을 추가해주면 된다
@Bean
public AuthenticationSuccessHandler successHandler() {
return ((request, response, authentication) -> {
DefaultOAuth2User defaultOAuth2User = (DefaultOAuth2User) authentication.getPrincipal();
String id = defaultOAuth2User.getAttributes().get("id").toString();
String email = defaultOAuth2User.getAttributes().get("kakao_account").toString();
// 이메일 주소를 찾았을 때만 값을 추출하여 사용
if (matcher.find()) {
email = matcher.group();
}
String body = """
{"id":"%s",
"email":"%s"}
""".formatted(id,email);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
});
}
(kakao_account 부분 이나 id 는 kakaoDeveloper 에서 확인할수있음)
그러면 login 에서 카카오 로그인을 하게 되면 아래처럼 보이게 된다
그런데 우리는 이부분이 다필요한게 아니라 angrybird24@naver.com 만 필요하다
그래서 간단하게 정규표현식으로 잘라서 넣어줬다
//앞코드 무시..
String id = defaultOAuth2User.getAttributes().get("id").toString();
String email = defaultOAuth2User.getAttributes().get("kakao_account").toString();
String regex = "\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
// 이메일 주소를 찾았을 때만 값을 추출하여 사용
if (matcher.find()) {
email = matcher.group();
}
String body = """
{"id":"%s",
"email":"%s"}
""".formatted(id,email);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
PrintWriter writer = response.getWriter();
writer.println(body);
writer.flush();
});
}
그렇게하면 이제 더이상 다른 필요없는게 없고
이렇게 id 와 email 값만 받아오게된다
그럼이제 이 불러온값을 DB에 저장해보자
DB(MySql) 에 저장하기
추가적으로 로그인 성공시 메인페이지 이동까지 해볼것이다
먼저 package 를 entity 만든뒤에 User 를 만들고 아래처럼 쓴다
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
@Table(name = "pet")
public class User {
@Id
private String email;
@Column
private String id;
}
필자는 email 를 (PK primary Key) 로 뒀지만 id 로 PK 로 해도 상관없다
그다음 repository 패키지를 만든뒤에 UserRepository 를 만들고 아래처럼 작성해주자
import com.codehows.animalcafe.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
// 추가적인 메서드가 필요하다면 여기에 정의할 수 있습니다.
}
그리고 service 패키지를 만든뒤에 UserService 를 만들고 아래처럼 작성해주자
import com.codehows.animalcafe.entity.User;
import com.codehows.animalcafe.repository.UserRepository;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void saveUserFromJson(String email,String id) {
User user = new User();
user.setEmail(email);
user.setId(id);
userRepository.save(user);
}
}
그리고 successHandler로 돌아와
//이전코드 생략..
String body = """
{"id":"%s",
"email":"%s"}
""".formatted(id,email);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
//db에 저장
userService.saveUserFromJson(email,id);
// PrintWriter writer = response.getWriter();
// writer.println(body);
// writer.flush();
// 로그인 성공시 메인페이지 이동
response.sendRedirect("/login/main");
PrintWriter 코드는 주석처리해주고
DB저장하는것과 login 페이지를 만들어주자
그리고는 LoginController에서 /main 을 추가해주자
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/login") //url 입력
public class LoginController {
@GetMapping
public String login(){
return "login";
}
@GetMapping("/main")
public String loginPage() {
return "main";
}
}
그뒤에 Templates 패키지에 main.html 을 만든뒤에 아래처럼 만들고
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Success</title>
</head>
<body>
<h1>Login Successful!</h1>
<p>Welcome to SARIMUS Animal Cafe!</p>
</body>
</html>
실행하면
성공적으로 로그인된다
그리도 DB 에 확인해보면 로그인 성공시에 메인화면으로 이동함과 동시에 db에 저장해준다
참고로 만약 같은 로그인 시켜줄시 if 문을 따로 만들어 같은 값이 안들어가거나 중복값이 안들어가게 하렸는데
알아서 잘 들어가졌다
만약 세션을 넣고싶으면
Controller 에 loginPage 부분에 아래처럼 수정하고
@GetMapping("/main")
public String loginPage(HttpSession session, Model model) {
String userId = (String) session.getAttribute("userId");
String userEmail = (String) session.getAttribute("userEmail");
//세션정보 확인
model.addAttribute("userId", userId);
model.addAttribute("userEmail", userEmail);
return "main";
}
SecurityConfig에 SuccessHandler 에다가도 아래를 추가한다
// 세션에 사용자 정보 저장
HttpSession session = request.getSession();
session.setAttribute("userId", id);
session.setAttribute("userEmail", email);
그리고 로그인 성공창 html에 thymeleaf 를 추가하고 아까 Controller에서 모델에 추가했던
userId 와 userEmail 을 출력하는코드를 추가해준뒤에 실행하면
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Success</title>
</head>
<body>
<h1>Login Successful!</h1>
<p>Welcome to SARIMUS Animal Cafe!</p>
<h1>Session Information</h1>
<div>
<p><strong>User ID:</strong> <span th:text="${userId}"></span></p>
<p><strong>User Email:</strong> <span th:text="${userEmail}"></span></p>
</div>
</body>
</html>
아래처럼 보이게되면 성공이다
로그아웃 (세션종료)
간단하다 SecurityFilter에 http.logout 을 만들어준다음에
logoutUrl 를 설정해주고
logoutSuccessUrl 로 로그아웃 성공시 /login 페이지로 다시이동시켜준뒤에
.deleteCookies 로 세션을 삭제한다
public SecurityConfig(OAuth2UserService oAuth2UserService) {
this.oAuth2UserService = oAuth2UserService;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf((csrf) ->
csrf.disable()
);
http.authorizeHttpRequests(config -> config.anyRequest().permitAll());
http.oauth2Login(oauth2Configurer -> oauth2Configurer
.loginPage("/login")
.successHandler(successHandler())
.userInfoEndpoint(userInfo -> userInfo
.userService(oAuth2UserService)));
http.logout(logout ->
logout
.logoutUrl("/logout") // 로그아웃 URL 설정
.logoutSuccessUrl("/login") // 로그아웃 성공 후 리다이렉트할 URL 설정
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
);
return http.build();
}
그리고 로그아웃 버튼을 메인페이지에서 추가하면 된다
<!-- 로그아웃 버튼 -->
<form action="/logout" method="post">
<button type="submit">Logout</button>
</form>
그러면 기존에 "JSESSIONID" 가 있던게 없어져있는걸 볼수가 있다
'Full Stack Course 풀스택과정 > SPRING' 카테고리의 다른 글
Springboot 상세검색 , 조건검색 및 페이징 (0) | 2024.05.22 |
---|---|
SpringBoot - OAuth2 로 카카오 로그인 (0) | 2024.05.10 |
스프링부트 비동기식 방명록 만들기 ( 2 ) (0) | 2024.05.06 |
스프링부트 비동기식 방명록 만들기 ( 1 ) (0) | 2024.05.06 |
SpringBoot - TOAST UI Editor 로 게시글 사진 업로드 (0) | 2024.04.24 |