반응형
- 카카오 로그인을 한 후 응답값을 고민을 좀 해봐야한다.
postgreSQL문으로 User table을 만들어보자
- PostgreSQL에서 User → 예약어라서 Users로 하던지 “User”로 해야됨
create table User(user_id INT auto_increment, email VARCHAR(100) not null, nickname VARCHAR(100) not null, profile VARCHAR(2000), primary key(user_id));
ERROR: syntax error at or near "User"
LINE 1: create table User(user_id INT auto_increment, email VARCHAR(...
User 클래스 이지만 테이블에 실제 이름은 users임
package com.Kkrap.Entity;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Entity
@Table(name = "users")
public class Users {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
@Setter
@Column(nullable = false)
private String email;
@Setter
@Column(nullable = false)
private String nickname;
@Setter
@Column(nullable = false)
private String profile;
@Setter
@Column(nullable = false)
private Long kakaoId;
// Links와의 관계 추가
@OneToMany(mappedBy = "users", cascade = CascadeType.ALL)
// @JsonIgnore // 순환 참조 방지
private List<Links> links;
@Builder
public Users(String email, String nickname, String profile, Long kakaoId)
{
this.email = email;
this.nickname = nickname;
this.profile = profile;
this.kakaoId = kakaoId;
}
public Users() {
// 기본 생성자
}
}
만약 jpa가 자동으로 쿼리문을 해주지 않으면 → application에 넣어주자
spring.jpa.hibernate.ddl-auto=update
이제 사용자의 정보를 DB안에 넣어보자.
UsersRepository
package com.Kkrap.Repository;
import com.Kkrap.Entity.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface UsersRepository extends JpaRepository<Users, Long>{
// @Query("SELECT userId from Users Where kakaoId = :kakaoId")
@Query("SELECT u FROM Users u WHERE u.kakaoId = :kakaoId")
Optional<Users> findByKaKaoId(@Param("kakaoId") Long kakaoId);
}
SecurityConfig.java
package com.Kkrap.Security;
import com.Kkrap.Entity.Users;
import com.Kkrap.Repository.UsersRepository;
import com.Kkrap.Service.CustomOAuth2UserService;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
@Autowired
private UsersRepository usersRepository;
private final CustomOAuth2UserService oAuth2UserService;
public SecurityConfig(CustomOAuth2UserService oAuth2UserService) {
this.oAuth2UserService = oAuth2UserService;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource())) // CORS 설정 추가
.csrf(csrf -> csrf.disable()) //
.authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll()
)
.oauth2Login(oauth2 -> oauth2
.loginPage("/login")
.userInfoEndpoint(userInfo -> userInfo
.userService(oAuth2UserService)
)
.successHandler(authenticationSuccessHandler()) // 로그인 성공 시 핸들러 사용
);
return http.build();
}
// CORS 설정
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("<http://172.20.10.12:3000>")); // 프론트엔드 주소 허용
configuration.setAllowedMethods(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name()));
configuration.setAllowCredentials(true); // 쿠키 및 인증 정보 허용
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
Object principal = authentication.getPrincipal();
if (principal instanceof DefaultOAuth2User) {
DefaultOAuth2User defaultOAuth2User = (DefaultOAuth2User) principal;
// 카카오 사용자 정보 추출
Map<String, Object> attributes = defaultOAuth2User.getAttributes();
String kaka_id = attributes.get("id").toString(); // 사용자 ID
Map<String, Object> kakaoAccount = (Map<String, Object>) attributes.get("kakao_account");
Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
String nickname = profile.get("nickname").toString(); // 사용자 닉네임
String profileImage = profile.get("profile_image_url").toString(); // 프로필 이미지 URL
String email = kakaoAccount.get("email").toString(); // 이메일
// 디버그용 로그 출력
System.out.println("카카오 사용자 ID: " + kaka_id);
System.out.println("카카오 사용자 닉네임: " + nickname);
System.out.println("카카오 사용자 이메일: " + email);
System.out.println("카카오 사용자 프로필 이미지 URL: " + profileImage);
// 사용자 정보를 각각 쿠키에 저장
setCookie(response, "kakao_id", kaka_id, 7 * 24 * 60 * 60); // 쿠키 유효기간 7일
setCookie(response, "nickname", nickname, 7 * 24 * 60 * 60);
setCookie(response, "profileImage", profileImage, 7 * 24 * 60 * 60);
setCookie(response, "email", email, 7 * 24 * 60 * 60);
//DB 로직 추가
String userId;
Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kaka_id));
System.out.println("CheckUser : " + CheckUser);
if (CheckUser.isEmpty()){
Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kaka_id));
usersRepository.save(newUser);
setCookie(response, "userId", String.valueOf(newUser.getUserId()), 7 * 24 * 60 * 60);
userId = String.valueOf(newUser.getUserId());
}
else
{
Users existingUser = CheckUser.get();
setCookie(response, "userId", String.valueOf(existingUser.getUserId()), 7 * 24 * 60 * 60);
userId = String.valueOf(existingUser.getUserId());
}
// 사용자 정보를 URL 인코딩
String redirectUrl = String.format(
"<http://localhost:3000/login/success?kakao_id=%s&nickname=%s&profileImage=%s&email=%s&userId=%s>",
URLEncoder.encode(kaka_id, tandardCharsets.UTF_8.toString()),
URLEncoder.encode(nickname, StandardCharsets.UTF_8.toString()),
URLEncoder.encode(profileImage, StandardCharsets.UTF_8.toString()),
URLEncoder.encode(email, StandardCharsets.UTF_8.toString()),
URLEncoder.encode(userId, StandardCharsets.UTF_8.toString())
);
// 리디렉션
response.sendRedirect(redirectUrl);
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid user principal type");
}
}
};
}
private void setCookie(HttpServletResponse response, String name, String value, int maxAge) {
Cookie cookie = new Cookie(name, value);
cookie.setPath("/");
cookie.setMaxAge(maxAge);
cookie.setHttpOnly(false); // JavaScript에서 접근 가능하도록 설정
cookie.setSecure(false); // HTTPS가 아닌 경우에도 전송되도록 설정
cookie.setDomain("43.203.234.0"); // 도메인을 프론트엔드 주소로 설정
response.addCookie(cookie);
}
}
DB 확인
반응형
'Spring Boot > [Spring boot] 개발' 카테고리의 다른 글
[Spring boot] Folder 데이터베이스 생성, 기능 추가 (0) | 2025.01.06 |
---|---|
[Spring boot] @ResponseEntity @ResponseBody 차이 (0) | 2025.01.05 |
[Spring boot] Link 데이터베이스 생성, 기능 추가 (0) | 2025.01.05 |
[Spring boot] JPA 쿼리 메서드 네이밍 및 테이블 및 칼럼 이름 매핑 (1) | 2025.01.05 |
[Spring boot] java22 → java21 컴파일 변경 (0) | 2025.01.05 |