From f0e5085edfcb75b881b9673054052871ebbbbc9b Mon Sep 17 00:00:00 2001 From: wjstmdduf Date: Mon, 20 Nov 2023 08:21:14 +0900 Subject: [PATCH 1/4] =?UTF-8?q?fix=20:=20global/aouth2=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trip/jwt/OAuth2LoginSuccessHandler.java | 49 +++++----- .../tgd/trip/user/domain/GoogleUserInfo.java | 34 ------- .../tgd/trip/user/domain/KakaoUserInfo.java | 35 ------- .../com/tgd/trip/user/domain/LoginDto.java | 10 -- .../tgd/trip/user/domain/NaverUserInfo.java | 37 -------- .../tgd/trip/user/domain/OAuth2UserInfo.java | 11 --- .../trip/user/service/CustomOAuth2User.java | 40 -------- .../trip/user/service/OAuth2UserService.java | 93 ------------------- .../trip/user/service/OAuthAttributes.java | 67 ------------- 9 files changed, 27 insertions(+), 349 deletions(-) delete mode 100644 src/main/java/com/tgd/trip/user/domain/GoogleUserInfo.java delete mode 100644 src/main/java/com/tgd/trip/user/domain/KakaoUserInfo.java delete mode 100644 src/main/java/com/tgd/trip/user/domain/LoginDto.java delete mode 100644 src/main/java/com/tgd/trip/user/domain/NaverUserInfo.java delete mode 100644 src/main/java/com/tgd/trip/user/domain/OAuth2UserInfo.java delete mode 100644 src/main/java/com/tgd/trip/user/service/CustomOAuth2User.java delete mode 100644 src/main/java/com/tgd/trip/user/service/OAuth2UserService.java delete mode 100644 src/main/java/com/tgd/trip/user/service/OAuthAttributes.java diff --git a/src/main/java/com/tgd/trip/jwt/OAuth2LoginSuccessHandler.java b/src/main/java/com/tgd/trip/jwt/OAuth2LoginSuccessHandler.java index 6016458..d9a519c 100644 --- a/src/main/java/com/tgd/trip/jwt/OAuth2LoginSuccessHandler.java +++ b/src/main/java/com/tgd/trip/jwt/OAuth2LoginSuccessHandler.java @@ -1,24 +1,21 @@ package com.tgd.trip.jwt; -import com.tgd.trip.security.LoginResponse; -import com.tgd.trip.user.service.CustomOAuth2User; +import com.tgd.trip.global.oauth2.dto.CustomOAuth2User; +import com.tgd.trip.user.domain.Role; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.core.user.DefaultOAuth2User; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.ui.Model; import javax.servlet.ServletException; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.net.URLEncoder; @Component @RequiredArgsConstructor @@ -32,22 +29,30 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { log.info("OAuth login 성공"); - log.info("뭔가뭔가날라옴 : {}", authentication); CustomOAuth2User oAuth2User = (CustomOAuth2User) authentication.getPrincipal(); - loginSuccess(response, oAuth2User); + loginSuccess(request, response, oAuth2User); } - private void loginSuccess(HttpServletResponse response, CustomOAuth2User oAuth2User) throws IOException { - String accessToken = jwtTokenProvider.createToken(oAuth2User.getEmail(), oAuth2User.getRoles()); - response.setHeader("Authorization", "Bearer " + accessToken); - log.info("oauth email : {} login success", oAuth2User.getEmail()); - log.info("accessToken : {}", accessToken); - response.getWriter().println(accessToken); - login(accessToken); - } + private void loginSuccess(HttpServletRequest request, HttpServletResponse response, CustomOAuth2User oAuth2User) throws IOException { + String accessToken = jwtTokenProvider.createToken(oAuth2User.getUserId(), oAuth2User.getRoles()); + + Cookie cookie = new Cookie("Authorization", accessToken); + + // 쿠키 설정 + cookie.setPath("/"); + cookie.setHttpOnly(false); + cookie.setSecure(true); // HTTPS를 사용할 때만 쿠키가 전송되도록 설정 + response.addCookie(cookie); // 쿠키를 응답에 추가 + + log.info("cookie : {}", cookie); + log.info("oauth email : {} login success", oAuth2User.getUserId()); + log.info("oauth role : {}", oAuth2User.getRoles()); + log.info("accessToken 여기까진 온다 : {}", accessToken); + + String redirectUrl = "http://localhost:5173/login"; + + log.info("Url : {}", redirectUrl); - public ResponseEntity login(String accessToken) { - String jwt = accessToken; - return ResponseEntity.ok(jwt); + response.sendRedirect(redirectUrl); } -} \ No newline at end of file +} diff --git a/src/main/java/com/tgd/trip/user/domain/GoogleUserInfo.java b/src/main/java/com/tgd/trip/user/domain/GoogleUserInfo.java deleted file mode 100644 index a8441ed..0000000 --- a/src/main/java/com/tgd/trip/user/domain/GoogleUserInfo.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.tgd.trip.user.domain; - -import lombok.Data; - -import java.util.Map; - -@Data -public class GoogleUserInfo implements OAuth2UserInfo{ - private Map attributes; - - public GoogleUserInfo(Map attributes) { - - this.attributes = attributes; - } - - @Override - public String getProviderId() { - return String.valueOf(attributes.get("sub")); } - - @Override - public String getProvider() { - return "google"; - } - - @Override - public String getEmail() { - return String.valueOf(attributes.get("email")); - } - - @Override - public String getName() { - return String.valueOf(attributes.get("name")); - } -} diff --git a/src/main/java/com/tgd/trip/user/domain/KakaoUserInfo.java b/src/main/java/com/tgd/trip/user/domain/KakaoUserInfo.java deleted file mode 100644 index 41fa8c3..0000000 --- a/src/main/java/com/tgd/trip/user/domain/KakaoUserInfo.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.tgd.trip.user.domain; - -import lombok.Data; - -import java.util.Map; - -@Data -public class KakaoUserInfo implements OAuth2UserInfo { - - private Map kakaoAccount; - - public KakaoUserInfo(Map attributes ) { - this.kakaoAccount = attributes; - } - - @Override - public String getProviderId() { - return String.valueOf(kakaoAccount.get("id")); - } - - @Override - public String getProvider() { - return "kakao"; - } - - @Override - public String getEmail() { - return String.valueOf(kakaoAccount.get("email")); - } - - @Override - public String getName() { - return String.valueOf(kakaoAccount.get("profile_nickname")); - } -} diff --git a/src/main/java/com/tgd/trip/user/domain/LoginDto.java b/src/main/java/com/tgd/trip/user/domain/LoginDto.java deleted file mode 100644 index 647df0c..0000000 --- a/src/main/java/com/tgd/trip/user/domain/LoginDto.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.tgd.trip.user.domain; - -import lombok.Getter; - -@Getter -public class LoginDto { - - private String email; - private String password; -} diff --git a/src/main/java/com/tgd/trip/user/domain/NaverUserInfo.java b/src/main/java/com/tgd/trip/user/domain/NaverUserInfo.java deleted file mode 100644 index 5ced173..0000000 --- a/src/main/java/com/tgd/trip/user/domain/NaverUserInfo.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.tgd.trip.user.domain; - -import lombok.Data; - -import java.util.Map; - -@Data -public class NaverUserInfo implements OAuth2UserInfo { - private Map attributes; // oauth2User.getAttributes() - - public NaverUserInfo(Map attributes) { - this.attributes = attributes; - } - - @Override - public String getProviderId() { - return String.valueOf(attributes.get("id")); - } - - @Override - public String getProvider() { - return "naver"; - } - - @Override - public String getEmail() { - - return String.valueOf(attributes.get("email")); - } - - @Override - public String getName() { - - return String.valueOf(attributes.get("name")); - - } -} diff --git a/src/main/java/com/tgd/trip/user/domain/OAuth2UserInfo.java b/src/main/java/com/tgd/trip/user/domain/OAuth2UserInfo.java deleted file mode 100644 index a28080b..0000000 --- a/src/main/java/com/tgd/trip/user/domain/OAuth2UserInfo.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.tgd.trip.user.domain; - -public interface OAuth2UserInfo { - String getProviderId(); - - String getProvider(); - - String getEmail(); - - String getName(); -} diff --git a/src/main/java/com/tgd/trip/user/service/CustomOAuth2User.java b/src/main/java/com/tgd/trip/user/service/CustomOAuth2User.java deleted file mode 100644 index 75fe244..0000000 --- a/src/main/java/com/tgd/trip/user/service/CustomOAuth2User.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.tgd.trip.user.service; - -import com.tgd.trip.user.domain.Role; -import com.tgd.trip.user.domain.User; -import com.tgd.trip.util.AuthorityUtils; -import lombok.Getter; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.core.user.DefaultOAuth2User; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -@Getter -public class CustomOAuth2User extends DefaultOAuth2User { - - private final String email; - private final List roles; - - public CustomOAuth2User(Collection authorities, - Map attributes, - String nameAttributeKey, - String email, - List roles) { - super(authorities, attributes, nameAttributeKey); - this.email = email; - this.roles = roles; - } - - public static CustomOAuth2User of(User user, Map attributes, OAuthAttributes oAuthAttributes) { - return new CustomOAuth2User( - AuthorityUtils.getAuthorities(user.getRoles()), - attributes, - oAuthAttributes.getProviderId(), - user.getEmail(), - user.getRoles()); - } -} \ No newline at end of file diff --git a/src/main/java/com/tgd/trip/user/service/OAuth2UserService.java b/src/main/java/com/tgd/trip/user/service/OAuth2UserService.java deleted file mode 100644 index 48ac79d..0000000 --- a/src/main/java/com/tgd/trip/user/service/OAuth2UserService.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.tgd.trip.user.service; - -import com.tgd.trip.jwt.JwtTokenProvider; -import com.tgd.trip.user.domain.*; -import com.tgd.trip.user.repository.UserRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.user.DefaultOAuth2User; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -@Slf4j -@Service -@RequiredArgsConstructor -public class OAuth2UserService extends DefaultOAuth2UserService { - private final UserRepository userRepository; - private final JwtTokenProvider jwtTokenProvider; - - //로그인 필요한 url 요청시 여기로 넘어옴 - @Override - @Transactional - public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { - log.info("userRequest: {}", userRequest); - - ClientRegistration clientRegistration = userRequest.getClientRegistration(); - log.info("clientRegistration :{}", clientRegistration); - OAuth2User oAuth2User = super.loadUser(userRequest); - - oAuth2User.getAuthorities().forEach((k) -> { - log.info("k: {}", k); - }); - - // oauth 회원가입 강제 등록 - OAuth2UserInfo oAuth2UserInfo = null; - - if (clientRegistration.getRegistrationId().equals("google")) { - log.info("구글 로그인 요청"); - oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes()); - log.info("oAuth2UserInfo: {}", oAuth2UserInfo); - } else if (userRequest.getClientRegistration().getRegistrationId().equals("naver")) { - oAuth2UserInfo = new NaverUserInfo((Map) oAuth2User.getAttributes().get("response")); - } else if (userRequest.getClientRegistration().getRegistrationId().equals("kakao")) { - oAuth2UserInfo = new KakaoUserInfo((Map) oAuth2User.getAttributes().get("kakao_account")); - } else { - log.info("우리는 구글과 페이스북만 지원합니다."); - } - System.out.println("유저정보" + oAuth2UserInfo); - - - String provider = oAuth2UserInfo.getProvider(); //google , naver, facebook etc - String providerId = clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); - String name = provider + "_" + oAuth2UserInfo.getName() + "_" + providerId; - String email = oAuth2UserInfo.getEmail(); - - log.info("email: {}", email); - log.info("name: {}", name); - Optional optionalUser = userRepository.findByEmail(email); - - User user = null; - System.out.println(user); - if (optionalUser.isPresent()) { - log.info("로그인을 이미 했음, 자동회원가입이 되어있다."); - user = optionalUser.get(); - } else { - user = User.builder() - .password("githere") - .name(name) - .email(email) - .roles(List.of(Role.USER.toString())) - .providerId(providerId) - .provider(provider) - .build(); - userRepository.save(user); - } - Map attributes = oAuth2User.getAttributes(); - OAuthAttributes authAttributes = OAuthAttributes.of(provider, providerId, attributes); - log.info("attributes : {}", attributes); - log.info("authAttributes : {}", authAttributes); - return CustomOAuth2User.of(user, attributes, authAttributes); - } - -} diff --git a/src/main/java/com/tgd/trip/user/service/OAuthAttributes.java b/src/main/java/com/tgd/trip/user/service/OAuthAttributes.java deleted file mode 100644 index 9df3186..0000000 --- a/src/main/java/com/tgd/trip/user/service/OAuthAttributes.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.tgd.trip.user.service; - - -import com.tgd.trip.exception.CustomException; -import com.tgd.trip.exception.ExceptionCode; -import com.tgd.trip.user.domain.*; -import lombok.Builder; -import lombok.Getter; -import org.springframework.security.crypto.password.PasswordEncoder; - -import java.util.Collections; -import java.util.Map; -import java.util.UUID; - -@Getter -public class OAuthAttributes { - private final String providerId; - private final OAuth2UserInfo oAuth2UserInfo; - - @Builder - public OAuthAttributes(String providerId, OAuth2UserInfo oAuth2UserInfo) { - this.providerId = providerId; - this.oAuth2UserInfo = oAuth2UserInfo; - } - - public static OAuthAttributes of(String provider, - String providerId, - Map attributes) { - System.out.println(providerId); - if (provider.equals(ProviderType.GOOGLE.getProvider())) { - return ofGoogle(providerId, attributes); - }else if(provider.equals(ProviderType.KAKAO.getProvider())){ - return ofKakao(providerId, attributes); - } - throw new CustomException(ExceptionCode.PROVIDER_NOT_FOUND); - } - - private static OAuthAttributes ofGoogle(String providerId, - Map attributes) { - return OAuthAttributes.builder() - .providerId(providerId) - .oAuth2UserInfo(new GoogleUserInfo(attributes)) - .build(); - } - - private static OAuthAttributes ofKakao(String providerId, - Map attributes) { - return OAuthAttributes.builder() - .providerId(providerId) - .oAuth2UserInfo(new KakaoUserInfo(attributes)) - .build(); - } - -// public User toEntity(OAuth2UserInfo oAuth2UserInfo, -// String username, -// String provider, -// PasswordEncoder passwordEncoder) { -// return new User( -// passwordEncoder.encode("OAUTH" + UUID.randomUUID()), -// username, -// oAuth2UserInfo.getEmail(), -// Collections.singletonList("ROLE_USER"), -// provider, -// oAuth2UserInfo.getProviderId() -// ); -// } -} From 0a76bc340f1bfba7d69accf671ff210a26eb4f03 Mon Sep 17 00:00:00 2001 From: wjstmdduf Date: Mon, 20 Nov 2023 08:22:46 +0900 Subject: [PATCH 2/4] . --- security | 2 +- .../tgd/trip/jwt/JwtAuthenticationFilter.java | 18 ++--- .../com/tgd/trip/jwt/JwtTokenProvider.java | 6 +- .../com/tgd/trip/security/SecurityConfig.java | 10 +-- .../com/tgd/trip/security/SecurityUser.java | 5 +- .../security/SecurityUserDetailService.java | 4 +- .../trip/user/controller/UserController.java | 43 +++++----- .../tgd/trip/user/domain/ProviderType.java | 16 ---- .../java/com/tgd/trip/user/domain/Role.java | 3 +- .../com/tgd/trip/user/domain/SignupDto.java | 28 +++++++ .../java/com/tgd/trip/user/domain/User.java | 9 ++- .../tgd/trip/user/domain/UserPrincipal.java | 80 ------------------- .../tgd/trip/user/service/UserService.java | 41 +++++++++- 13 files changed, 122 insertions(+), 143 deletions(-) delete mode 100644 src/main/java/com/tgd/trip/user/domain/ProviderType.java create mode 100644 src/main/java/com/tgd/trip/user/domain/SignupDto.java delete mode 100644 src/main/java/com/tgd/trip/user/domain/UserPrincipal.java diff --git a/security b/security index 7659b0b..b542bab 160000 --- a/security +++ b/security @@ -1 +1 @@ -Subproject commit 7659b0b462b6a28f8a84964186a5a1a500a853c3 +Subproject commit b542babda8899266d008cc201b18fab7e73a987b diff --git a/src/main/java/com/tgd/trip/jwt/JwtAuthenticationFilter.java b/src/main/java/com/tgd/trip/jwt/JwtAuthenticationFilter.java index 1840942..0cc04c9 100644 --- a/src/main/java/com/tgd/trip/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/tgd/trip/jwt/JwtAuthenticationFilter.java @@ -1,37 +1,31 @@ package com.tgd.trip.jwt; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.tgd.trip.user.domain.LoginDto; import lombok.RequiredArgsConstructor; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.filter.GenericFilterBean; +import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @RequiredArgsConstructor -public class JwtAuthenticationFilter extends GenericFilterBean { +public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtTokenProvider jwtTokenProvider; @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 헤더에서 JWT를 받아옴 String token = jwtTokenProvider.resolveToken((HttpServletRequest) request); + System.out.println("요청 헤더에 있는 토큰" + token); // 유효한 토큰인지 확인 if (token != null && jwtTokenProvider.validateToken(token)) { // 토큰이 유효하면 토큰으로부터 유저 정보를 받아옴 Authentication authentication = jwtTokenProvider.getAuthentication(token); + System.out.println(authentication.getPrincipal()); // SecurityContext에 Authentication 객체를 저장 // System.out.println(authentication.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); @@ -39,6 +33,6 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha // logger.debug("Security Context에 '{}' 인증 정보를 저장했습니다, uri: {}", authentication.getName(), requestURI); } - chain.doFilter(request, response); + filterChain.doFilter(request, response); } } diff --git a/src/main/java/com/tgd/trip/jwt/JwtTokenProvider.java b/src/main/java/com/tgd/trip/jwt/JwtTokenProvider.java index 11a0538..6e9ac63 100644 --- a/src/main/java/com/tgd/trip/jwt/JwtTokenProvider.java +++ b/src/main/java/com/tgd/trip/jwt/JwtTokenProvider.java @@ -34,8 +34,8 @@ public class JwtTokenProvider { // } // JWT 토큰 생성 - public String createToken(String userPK, List roles) { - Claims claims = Jwts.claims().setSubject(userPK); // JWT payload에 저장되는 정보 단위 + public String createToken(Long userPK, List roles) { + Claims claims = Jwts.claims().setSubject(userPK.toString()); // JWT payload에 저장되는 정보 단위 claims.put("roles", roles); // 정보 저장 (key-value) Date now = new Date(); return Jwts.builder() @@ -49,6 +49,7 @@ public String createToken(String userPK, List roles) { // JWT 토큰에서 인증 정보 조회 public Authentication getAuthentication(String token) { + System.out.println("여기느옴?"); // UserDetails userDetails = userDetailsService.loadUserByUsername(this.getUserPK(token)); SecurityUser userDetails = (SecurityUser) userDetailsService.loadUserByUsername(this.getUserPK(token)); // System.out.println(userDetails.getAuthorities()); @@ -62,6 +63,7 @@ public String getUserPK(String token) { // Request의 Header에서 token 값을 가져옵니다. "X-AUTH-TOKEN": "TOKEN 값" public String resolveToken(HttpServletRequest request) { + System.out.println("여기는 옴?222222"); return request.getHeader("X-AUTH-TOKEN"); } diff --git a/src/main/java/com/tgd/trip/security/SecurityConfig.java b/src/main/java/com/tgd/trip/security/SecurityConfig.java index 97b2553..0659831 100644 --- a/src/main/java/com/tgd/trip/security/SecurityConfig.java +++ b/src/main/java/com/tgd/trip/security/SecurityConfig.java @@ -51,14 +51,14 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .cors().configurationSource(corsConfigurationSource()) // CORS 구성을 위한 설정 소스를 지정합니다. .and() - .headers().frameOptions().disable() // X-Frame-Options를 비활성화합니다. +// .headers().frameOptions().disable() // X-Frame-Options를 비활성화합니다. - .and() +// .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션을 상태 없이 관리합니다. .and() .authorizeRequests() // 요청에 대한 사용 권한 체크 시작 - .antMatchers(HttpMethod.GET,"/api/user/**").authenticated() + .antMatchers("/api/user/**").authenticated() .anyRequest().permitAll() .and().addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class) @@ -75,12 +75,12 @@ public CorsConfigurationSource corsConfigurationSource() { // CORS 구성을 위한 CorsConfigurationSource를 설정합니다. CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(List.of("*")); // 모든 Origin을 허용합니다. +// configuration.setAllowedOrigins(List.of("*")); // 모든 Origin을 허용합니다. + configuration.setAllowedOriginPatterns(List.of("*")); configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PATCH", "PUT", "DELETE", "HEAD")); // 허용할 HTTP 메서드를 설정합니다. configuration.setAllowedHeaders(List.of("*")); // 모든 헤더를 허용합니다. configuration.setExposedHeaders(List.of("*")); // 노출할 헤더를 설정합니다. configuration.setAllowCredentials(false); // 인증 정보를 포함하지 않도록 설정합니다. - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); // 모든 경로에 대해 CORS 구성을 적용합니다. diff --git a/src/main/java/com/tgd/trip/security/SecurityUser.java b/src/main/java/com/tgd/trip/security/SecurityUser.java index 0e5e841..cac15df 100644 --- a/src/main/java/com/tgd/trip/security/SecurityUser.java +++ b/src/main/java/com/tgd/trip/security/SecurityUser.java @@ -1,14 +1,17 @@ package com.tgd.trip.security; +import lombok.extern.log4j.Log4j; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; +@Slf4j public class SecurityUser extends User { private com.tgd.trip.user.domain.User user; public SecurityUser(com.tgd.trip.user.domain.User user) { super(user.getEmail(), user.getPassword(), - AuthorityUtils.createAuthorityList("ROLE_"+user.getRoles())); + AuthorityUtils.createAuthorityList("ROLE_" + user.getRoles().stream().findFirst().get())); this.user = user; } diff --git a/src/main/java/com/tgd/trip/security/SecurityUserDetailService.java b/src/main/java/com/tgd/trip/security/SecurityUserDetailService.java index 0a0c7e6..214ea63 100644 --- a/src/main/java/com/tgd/trip/security/SecurityUserDetailService.java +++ b/src/main/java/com/tgd/trip/security/SecurityUserDetailService.java @@ -20,9 +20,7 @@ public SecurityUserDetailService(UserRepository mapper) { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { -// System.out.println("loadByUserName"); - - Optional user = repo.findByEmail(username); + Optional user = repo.findById(Long.parseLong(username)); if (user == null) { throw new UsernameNotFoundException(username + " 사용자 없음"); } else { diff --git a/src/main/java/com/tgd/trip/user/controller/UserController.java b/src/main/java/com/tgd/trip/user/controller/UserController.java index ea464f3..c9324b1 100644 --- a/src/main/java/com/tgd/trip/user/controller/UserController.java +++ b/src/main/java/com/tgd/trip/user/controller/UserController.java @@ -2,23 +2,15 @@ import com.tgd.trip.jwt.JwtTokenProvider; import com.tgd.trip.security.SecurityUser; -import com.tgd.trip.user.domain.User; -import com.tgd.trip.user.domain.UserPrincipal; -import com.tgd.trip.user.repository.UserRepository; -import com.tgd.trip.user.service.OAuth2UserService; +import com.tgd.trip.user.domain.SignupDto; +import com.tgd.trip.user.service.UserService; import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.web.bind.annotation.*; -import java.util.Map; -import java.util.Optional; - @RequiredArgsConstructor @RestController @RequestMapping("/api/user") @@ -26,15 +18,30 @@ public class UserController { private final PasswordEncoder passwordEncoder; private final JwtTokenProvider jwtTokenProvider; - private final UserRepository reop; + private final UserService userService; - @GetMapping("/login/test") - public ResponseEntity test(@AuthenticationPrincipal UserPrincipal securityUser){ - log.info("테스트 요청 토큰 : {}", securityUser); - if (securityUser.getAuthorities().stream().anyMatch(auth -> auth.getAuthority().equals("ROLE_USER"))) - return ResponseEntity.ok("OK"); - else - return ResponseEntity.ok("fail"); + @GetMapping("/signup") + public ResponseEntity signup(@AuthenticationPrincipal SecurityUser securityUser, @RequestParam Long userId) { + + SignupDto tempuser = null; + System.out.println(userId); + if (securityUser.getAuthorities().stream().anyMatch(auth -> auth.getAuthority().equals("ROLE_GEST"))) { // 요청한 유저가 게스트 라면 + tempuser = userService.getSignup(userId); + } + + return ResponseEntity.ok(tempuser); + } + + @PostMapping("/signup") + public ResponseEntity signup(@AuthenticationPrincipal SecurityUser securityUser, + @RequestBody SignupDto userInfo) { + System.out.println("회원가입 추가정보 받음!!!" + userInfo); + String newToken = null; + if (securityUser.getAuthorities().stream().anyMatch(auth -> auth.getAuthority().equals("ROLE_GEST"))) { // 요청한 유저가 게스트 라면 + newToken = userService.postSignup(userInfo); + } + + return ResponseEntity.ok(newToken); } @GetMapping("/test") diff --git a/src/main/java/com/tgd/trip/user/domain/ProviderType.java b/src/main/java/com/tgd/trip/user/domain/ProviderType.java deleted file mode 100644 index ff9012e..0000000 --- a/src/main/java/com/tgd/trip/user/domain/ProviderType.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.tgd.trip.user.domain; - -import lombok.Getter; - -public enum ProviderType { - GOOGLE("google"), - NAVER("naver"), - - KAKAO("kakao"); - - @Getter - private final String provider; - - - ProviderType(String provider){this.provider = provider;} -} diff --git a/src/main/java/com/tgd/trip/user/domain/Role.java b/src/main/java/com/tgd/trip/user/domain/Role.java index 02c6f6a..9081375 100644 --- a/src/main/java/com/tgd/trip/user/domain/Role.java +++ b/src/main/java/com/tgd/trip/user/domain/Role.java @@ -7,7 +7,8 @@ @ToString public enum Role { USER("일반유저"), - ADMIN("어드민"); + ADMIN("어드민"), + GEST("처음 접속한 유저"); private final String role; } diff --git a/src/main/java/com/tgd/trip/user/domain/SignupDto.java b/src/main/java/com/tgd/trip/user/domain/SignupDto.java new file mode 100644 index 0000000..9f017c3 --- /dev/null +++ b/src/main/java/com/tgd/trip/user/domain/SignupDto.java @@ -0,0 +1,28 @@ +package com.tgd.trip.user.domain; + +import lombok.*; + +import java.time.LocalDate; + +@ToString +@Getter +@Setter +@AllArgsConstructor +public class SignupDto { + private Long userId; + private String name; + private String email; + private LocalDate birth; + private String nickName; + private Boolean sex; + + @Builder + public SignupDto(User user) { + this.userId = user.getUserId(); + this.name = user.getName(); + this.email = user.getEmail(); + this.birth = user.getBirth(); + this.nickName = user.getNickName(); + this.sex = user.getSex(); + } +} diff --git a/src/main/java/com/tgd/trip/user/domain/User.java b/src/main/java/com/tgd/trip/user/domain/User.java index f40bff8..1bcbab8 100644 --- a/src/main/java/com/tgd/trip/user/domain/User.java +++ b/src/main/java/com/tgd/trip/user/domain/User.java @@ -1,12 +1,15 @@ package com.tgd.trip.user.domain; +import com.tgd.trip.attraction.domain.AttractionBookmark; import com.tgd.trip.global.BaseEntity; +import com.tgd.trip.schedule.domain.ScheduleBookmark; import lombok.*; import javax.persistence.*; import javax.validation.constraints.NotNull; -import javax.validation.constraints.Null; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; @Entity @Getter @@ -24,8 +27,8 @@ public class User extends BaseEntity { @Column(unique = true) private String email; @NotNull - @ElementCollection - private List roles = new ArrayList(); + @ElementCollection(fetch = FetchType.EAGER) + private List roles = new ArrayList<>(); private String provider; private String providerId; private UserStatus status=UserStatus.ACTIVE; diff --git a/src/main/java/com/tgd/trip/user/domain/UserPrincipal.java b/src/main/java/com/tgd/trip/user/domain/UserPrincipal.java deleted file mode 100644 index 4bcc111..0000000 --- a/src/main/java/com/tgd/trip/user/domain/UserPrincipal.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.tgd.trip.user.domain; - -import com.tgd.trip.util.AuthorityUtils; -import lombok.Getter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.core.user.OAuth2User; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -@Getter -public class UserPrincipal implements UserDetails, OAuth2User { - - private final User user; - private Map attributes; - - public UserPrincipal(User user) { - this.user = user; - } - - public UserPrincipal(User user, Map attributes) { - this.user = user; - this.attributes = attributes; - } - - public static UserPrincipal of(User user) { - return new UserPrincipal(user); - } - - public static UserPrincipal of(User user, Map attributes) { - return new UserPrincipal(user, attributes); - } - - @Override - public Map getAttributes() { - return attributes; - } - - @Override - public Collection getAuthorities() { - return AuthorityUtils.getAuthorities(List.of(user.getRoles().toString())); - } - - @Override - public String getPassword() { - return user.getPassword(); - } - - @Override - public String getUsername() { - return user.getEmail(); - } - - @Override - public String getName() { - return attributes.get(user.getProviderId()).toString(); - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } -} diff --git a/src/main/java/com/tgd/trip/user/service/UserService.java b/src/main/java/com/tgd/trip/user/service/UserService.java index 96ec9db..54657c3 100644 --- a/src/main/java/com/tgd/trip/user/service/UserService.java +++ b/src/main/java/com/tgd/trip/user/service/UserService.java @@ -1,16 +1,22 @@ package com.tgd.trip.user.service; +import com.tgd.trip.jwt.JwtTokenProvider; +import com.tgd.trip.user.domain.Role; +import com.tgd.trip.user.domain.SignupDto; import com.tgd.trip.user.domain.User; import com.tgd.trip.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Optional; + @RequiredArgsConstructor @Service public class UserService { private final UserRepository userRepository; - + private final JwtTokenProvider provider; public User getVerifyUser(String email) { return userRepository.findByEmail(email).orElseThrow(); } @@ -19,6 +25,39 @@ public User getVerifyUser(Long id) { return userRepository.findById(id).orElseThrow(); } + public SignupDto getSignup(Long userId) { + User user = null; + SignupDto tempuser = null; + Optional optionalUser = userRepository.findById(userId); + if (optionalUser.isPresent()) { + user = optionalUser.get(); + tempuser = new SignupDto(user); + } + + return tempuser; + } + + public String postSignup(SignupDto user) { + String newToken = null; + //signupDto로 추가정보 안한 유저 정보 가져옴 + Optional optionalUser = userRepository.findById(user.getUserId()); + if (optionalUser.isPresent()) { + User oldUser = optionalUser.get(); + oldUser.setNickName(user.getNickName()); + oldUser.setBirth(user.getBirth()); + oldUser.setSex(user.getSex()); + oldUser.setRoles(List.of(Role.USER.name())); + System.out.println(oldUser); + + userRepository.save(oldUser); + + newToken = provider.createToken(oldUser.getUserId(), oldUser.getRoles()); + } + + return newToken; + } + + public void createUser(User user) { userRepository.save(user); } From deb1897316544c53f4de73615f09d7313db5def2 Mon Sep 17 00:00:00 2001 From: wjstmdduf Date: Mon, 20 Nov 2023 08:23:20 +0900 Subject: [PATCH 3/4] . --- .../oauth2/controller/OAuth2Controller.java | 48 +++++++++ .../global/oauth2/dto/CustomOAuth2User.java | 39 ++++++++ .../tgd/trip/global/oauth2/dto/LoginDto.java | 10 ++ .../trip/global/oauth2/dto/ProviderType.java | 16 +++ .../global/oauth2/dto/SocialLoginRequest.java | 14 +++ .../oauth2/dto/UserInfo/GoogleUserInfo.java | 34 +++++++ .../oauth2/dto/UserInfo/KakaoUserInfo.java | 35 +++++++ .../oauth2/dto/UserInfo/NaverUserInfo.java | 37 +++++++ .../oauth2/dto/UserInfo/OAuth2UserInfo.java | 11 +++ .../CustomOAuth2UserRequestFactory.java | 67 +++++++++++++ .../oauth2/service/OAuth2UserService.java | 97 +++++++++++++++++++ .../global/oauth2/util/LoginResponse.java | 14 +++ .../global/oauth2/util/OAuthAttributes.java | 77 +++++++++++++++ .../global/oauth2/util/UserPrincipal.java | 81 ++++++++++++++++ 14 files changed, 580 insertions(+) create mode 100644 src/main/java/com/tgd/trip/global/oauth2/controller/OAuth2Controller.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/CustomOAuth2User.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/LoginDto.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/ProviderType.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/SocialLoginRequest.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/GoogleUserInfo.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/KakaoUserInfo.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/NaverUserInfo.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/OAuth2UserInfo.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/service/CustomOAuth2UserRequestFactory.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/service/OAuth2UserService.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/util/LoginResponse.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/util/OAuthAttributes.java create mode 100644 src/main/java/com/tgd/trip/global/oauth2/util/UserPrincipal.java diff --git a/src/main/java/com/tgd/trip/global/oauth2/controller/OAuth2Controller.java b/src/main/java/com/tgd/trip/global/oauth2/controller/OAuth2Controller.java new file mode 100644 index 0000000..94ca7fc --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/controller/OAuth2Controller.java @@ -0,0 +1,48 @@ +//package com.tgd.trip.global.oauth2.controller; +// +//import com.tgd.trip.global.oauth2.dto.SocialLoginRequest; +//import com.tgd.trip.global.oauth2.util.LoginResponse; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.http.ResponseEntity; +//import org.springframework.security.core.userdetails.UserDetails; +//import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +//import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +//import org.springframework.web.bind.annotation.*; +// +//import javax.validation.Valid; +//import java.net.URI; +//import java.util.Map; +// +//@RequiredArgsConstructor +//@RestController +//@RequestMapping("/api/oauth2") +//@Slf4j +//public class OAuth2Controller { +// private final OAuth2UserService oAuth2UserService; +// +// @PostMapping("/social-login") +// public ResponseEntity getUserInfo(@RequestBody Map request) { +// String accessToken = request.get("accessToken"); +// +// // OAuth2UserRequest를 생성하기 위해 OAuth2UserRequestFactory를 주입받아 사용 +// OAuth2UserRequestFactory userRequestFactory = ...; // OAuth2UserRequestFactory 주입 +// +// // OAuth2UserRequest를 생성하여 accessToken을 전달 +// OAuth2UserRequest userRequest = userRequestFactory.createOAuth2UserRequest("google", accessToken); +// +// // OAuth2UserService의 loadUser 메서드를 호출하여 OAuth2User를 가져옴 +// OAuth2User oAuth2User = oAuth2UserService.loadUser(userRequest); +// +// // OAuth2User를 활용하여 로그인 로직 처리 +// // ... +// +// return ResponseEntity.ok("로그인 성공"); +// } +// @GetMapping("/{id}") +// public ResponseEntity getUser(@PathVariable("id") Long id) { +// return ResponseEntity.ok( +// userService.getUser(id) +// ); +// } +//} diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/CustomOAuth2User.java b/src/main/java/com/tgd/trip/global/oauth2/dto/CustomOAuth2User.java new file mode 100644 index 0000000..8f882af --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/CustomOAuth2User.java @@ -0,0 +1,39 @@ +package com.tgd.trip.global.oauth2.dto; + +import com.tgd.trip.global.oauth2.util.OAuthAttributes; +import com.tgd.trip.user.domain.User; +import com.tgd.trip.util.AuthorityUtils; +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +@Getter +public class CustomOAuth2User extends DefaultOAuth2User { + + private final List roles; + private final Long userId; + + public CustomOAuth2User(Collection authorities, + Map attributes, + String nameAttributeKey, + Long userId, + List roles) { + super(authorities, attributes, nameAttributeKey); + this.roles = roles; + this.userId = userId; + } + + public static CustomOAuth2User of(User user, Map attributes, OAuthAttributes oAuthAttributes) { + return new CustomOAuth2User( + AuthorityUtils.getAuthorities(user.getRoles()), + attributes, + oAuthAttributes.getProviderId(), + user.getUserId(), + user.getRoles() + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/LoginDto.java b/src/main/java/com/tgd/trip/global/oauth2/dto/LoginDto.java new file mode 100644 index 0000000..e0c039c --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/LoginDto.java @@ -0,0 +1,10 @@ +package com.tgd.trip.global.oauth2.dto; + +import lombok.Getter; + +@Getter +public class LoginDto { + + private String email; + private String password; +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/ProviderType.java b/src/main/java/com/tgd/trip/global/oauth2/dto/ProviderType.java new file mode 100644 index 0000000..97d7f2a --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/ProviderType.java @@ -0,0 +1,16 @@ +package com.tgd.trip.global.oauth2.dto; + +import lombok.Getter; + +public enum ProviderType { + GOOGLE("google"), + NAVER("naver"), + + KAKAO("kakao"); + + @Getter + private final String provider; + + + ProviderType(String provider){this.provider = provider;} +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/SocialLoginRequest.java b/src/main/java/com/tgd/trip/global/oauth2/dto/SocialLoginRequest.java new file mode 100644 index 0000000..c37a49f --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/SocialLoginRequest.java @@ -0,0 +1,14 @@ +package com.tgd.trip.global.oauth2.dto; + +import com.tgd.trip.global.oauth2.dto.ProviderType; +import lombok.Getter; + +import javax.validation.constraints.NotNull; + +@Getter +public class SocialLoginRequest { + @NotNull + private ProviderType userType; + @NotNull + private String code; +} \ No newline at end of file diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/GoogleUserInfo.java b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/GoogleUserInfo.java new file mode 100644 index 0000000..b368f9f --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/GoogleUserInfo.java @@ -0,0 +1,34 @@ +package com.tgd.trip.global.oauth2.dto.UserInfo; + +import lombok.Data; + +import java.util.Map; + +@Data +public class GoogleUserInfo implements OAuth2UserInfo{ + private Map attributes; + + public GoogleUserInfo(Map attributes) { + + this.attributes = attributes; + } + + @Override + public String getProviderId() { + return String.valueOf(attributes.get("sub")); } + + @Override + public String getProvider() { + return "google"; + } + + @Override + public String getEmail() { + return String.valueOf(attributes.get("email")); + } + + @Override + public String getName() { + return String.valueOf(attributes.get("name")); + } +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/KakaoUserInfo.java b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/KakaoUserInfo.java new file mode 100644 index 0000000..5f406c9 --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/KakaoUserInfo.java @@ -0,0 +1,35 @@ +package com.tgd.trip.global.oauth2.dto.UserInfo; + +import lombok.Data; + +import java.util.Map; + +@Data +public class KakaoUserInfo implements OAuth2UserInfo { + + private Map kakaoAccount; + + public KakaoUserInfo(Map attributes ) { + this.kakaoAccount = attributes; + } + + @Override + public String getProviderId() { + return String.valueOf(kakaoAccount.get("id")); + } + + @Override + public String getProvider() { + return "kakao"; + } + + @Override + public String getEmail() { + return String.valueOf(kakaoAccount.get("email")); + } + + @Override + public String getName() { + return String.valueOf(kakaoAccount.get("profile_nickname")); + } +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/NaverUserInfo.java b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/NaverUserInfo.java new file mode 100644 index 0000000..c182f1e --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/NaverUserInfo.java @@ -0,0 +1,37 @@ +package com.tgd.trip.global.oauth2.dto.UserInfo; + +import lombok.Data; + +import java.util.Map; + +@Data +public class NaverUserInfo implements OAuth2UserInfo { + private Map attributes; // oauth2User.getAttributes() + + public NaverUserInfo(Map attributes) { + this.attributes = attributes; + } + + @Override + public String getProviderId() { + return String.valueOf(attributes.get("id")); + } + + @Override + public String getProvider() { + return "naver"; + } + + @Override + public String getEmail() { + + return String.valueOf(attributes.get("email")); + } + + @Override + public String getName() { + + return String.valueOf(attributes.get("name")); + + } +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/OAuth2UserInfo.java b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/OAuth2UserInfo.java new file mode 100644 index 0000000..dca4e13 --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/dto/UserInfo/OAuth2UserInfo.java @@ -0,0 +1,11 @@ +package com.tgd.trip.global.oauth2.dto.UserInfo; + +public interface OAuth2UserInfo { + String getProviderId(); + + String getProvider(); + + String getEmail(); + + String getName(); +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/service/CustomOAuth2UserRequestFactory.java b/src/main/java/com/tgd/trip/global/oauth2/service/CustomOAuth2UserRequestFactory.java new file mode 100644 index 0000000..70de9da --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/service/CustomOAuth2UserRequestFactory.java @@ -0,0 +1,67 @@ +//package com.tgd.trip.global.oauth2.service; +// +//import org.springframework.security.oauth2.client.registration.ClientRegistration; +//import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +//import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +//import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +//import org.springframework.security.oauth2.core.OAuth2AccessToken; +//import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +//import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +//import org.springframework.stereotype.Service; +// +//@Service +//public class CustomOAuth2UserRequestFactory implements OAuth2UserRequestFactory { +// +// private final ClientRegistrationRepository clientRegistrationRepository; +// private final OAuth2UserRequestRepository userRequestRepository; +// +// public CustomOAuth2UserRequestFactory(ClientRegistrationRepository clientRegistrationRepository, +// OAuth2UserRequestRepository userRequestRepository) { +// this.clientRegistrationRepository = clientRegistrationRepository; +// this.userRequestRepository = userRequestRepository; +// } +// +// @Override +// public OAuth2UserRequest createOAuth2UserRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken) { +// AuthenticationMethod authenticationMethod = AuthenticationMethod.CLIENT_SECRET_BASIC; +// if (clientRegistration.getClientAuthenticationMethod() == ClientAuthenticationMethod.NONE) { +// authenticationMethod = AuthenticationMethod.NONE; +// } +// +// OAuth2UserRequest.Builder builder = OAuth2UserRequest.withClientRegistration(clientRegistration) +// .accessToken(accessToken) +// .authenticationMethod(authenticationMethod); +// +// OAuth2UserRequest userRequest = builder.build(); +// this.userRequestRepository.saveUserRequest(userRequest, null); +// +// return userRequest; +// } +// +// @Override +// public OAuth2UserRequest createOAuth2UserRequest(String registrationId, OAuth2AccessToken accessToken) { +// ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId); +// if (clientRegistration == null) { +// throw new IllegalArgumentException("Invalid Client Registration with Id: " + registrationId); +// } +// +// return createOAuth2UserRequest(clientRegistration, accessToken); +// } +// +// @Override +// public OAuth2UserRequest createOAuth2UserRequest(OAuth2AuthorizationRequest authorizationRequest) { +// String registrationId = authorizationRequest.getAttribute(OAuth2ParameterNames.REGISTRATION_ID); +// if (registrationId == null) { +// throw new IllegalArgumentException("Missing Client Registration Id"); +// } +// +// ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId); +// if (clientRegistration == null) { +// throw new IllegalArgumentException("Invalid Client Registration with Id: " + registrationId); +// } +// +// OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, +// "your_access_token_here", null, null); +// return createOAuth2UserRequest(clientRegistration, accessToken); +// } +//} diff --git a/src/main/java/com/tgd/trip/global/oauth2/service/OAuth2UserService.java b/src/main/java/com/tgd/trip/global/oauth2/service/OAuth2UserService.java new file mode 100644 index 0000000..316ede6 --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/service/OAuth2UserService.java @@ -0,0 +1,97 @@ +package com.tgd.trip.global.oauth2.service; + +import com.tgd.trip.global.oauth2.dto.CustomOAuth2User; +import com.tgd.trip.global.oauth2.dto.UserInfo.GoogleUserInfo; +import com.tgd.trip.global.oauth2.dto.UserInfo.KakaoUserInfo; +import com.tgd.trip.global.oauth2.dto.UserInfo.NaverUserInfo; +import com.tgd.trip.global.oauth2.dto.UserInfo.OAuth2UserInfo; +import com.tgd.trip.global.oauth2.util.OAuthAttributes; +import com.tgd.trip.jwt.JwtTokenProvider; +import com.tgd.trip.user.domain.*; +import com.tgd.trip.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.CrossOrigin; + +import java.util.Map; + + +import java.util.*; + +@Slf4j +@Service +@RequiredArgsConstructor +public class OAuth2UserService extends DefaultOAuth2UserService { + private final UserRepository userRepository; + + //로그인 필요한 url 요청시 여기로 넘어옴 + @Override + @Transactional + @CrossOrigin(origins = "http://localhost:5173") + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + log.info("userRequest: {}", userRequest); + + ClientRegistration clientRegistration = userRequest.getClientRegistration(); + log.info("clientRegistration :{}", clientRegistration); + OAuth2User oAuth2User = super.loadUser(userRequest); + + oAuth2User.getAuthorities().forEach((k) -> { + log.info("k: {}", k); + }); + + // oauth 회원가입 강제 등록 + OAuth2UserInfo oAuth2UserInfo = null; + + if (clientRegistration.getRegistrationId().equals("google")) { + log.info("구글 로그인 요청"); + oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes()); + log.info("oAuth2UserInfo: {}", oAuth2UserInfo); + } else if (userRequest.getClientRegistration().getRegistrationId().equals("naver")) { + oAuth2UserInfo = new NaverUserInfo((Map) oAuth2User.getAttributes().get("response")); + } else if (userRequest.getClientRegistration().getRegistrationId().equals("kakao")) { + oAuth2UserInfo = new KakaoUserInfo((Map) oAuth2User.getAttributes().get("kakao_account")); + } else { + log.info("우리는 구글과 페이스북만 지원합니다."); + } + System.out.println("유저정보" + oAuth2UserInfo); + + + String provider = oAuth2UserInfo.getProvider(); //google , naver, facebook etc + String providerId = clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); + String name = oAuth2UserInfo.getName(); + String email = oAuth2UserInfo.getEmail(); + + log.info("email: {}", email); + log.info("name: {}", name); + Optional optionalUser = userRepository.findByEmail(email); + + User user = null; + if (optionalUser.isPresent()) { + log.info("로그인을 이미 했음, 자동회원가입이 되어있다."); + user = optionalUser.get(); + } else { + user = User.builder() + .password("githere") + .name(name) + .email(email) + .roles(List.of(Role.GEST.name())) + .providerId(providerId) + .provider(provider) + .build(); + userRepository.save(user); + } + Map attributes = oAuth2User.getAttributes(); + OAuthAttributes authAttributes = OAuthAttributes.of(provider, providerId, attributes); + log.info("attributes : {}", attributes); + log.info("authAttributes : {}", authAttributes); + return CustomOAuth2User.of(user, attributes, authAttributes); + } + +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/util/LoginResponse.java b/src/main/java/com/tgd/trip/global/oauth2/util/LoginResponse.java new file mode 100644 index 0000000..f04b7eb --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/util/LoginResponse.java @@ -0,0 +1,14 @@ +package com.tgd.trip.global.oauth2.util; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class LoginResponse { + private Long id; +} \ No newline at end of file diff --git a/src/main/java/com/tgd/trip/global/oauth2/util/OAuthAttributes.java b/src/main/java/com/tgd/trip/global/oauth2/util/OAuthAttributes.java new file mode 100644 index 0000000..ee93f92 --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/util/OAuthAttributes.java @@ -0,0 +1,77 @@ +package com.tgd.trip.global.oauth2.util; + + +import com.tgd.trip.exception.CustomException; +import com.tgd.trip.exception.ExceptionCode; +import com.tgd.trip.global.oauth2.dto.ProviderType; +import com.tgd.trip.global.oauth2.dto.UserInfo.GoogleUserInfo; +import com.tgd.trip.global.oauth2.dto.UserInfo.KakaoUserInfo; +import com.tgd.trip.global.oauth2.dto.UserInfo.OAuth2UserInfo; +import lombok.Builder; +import lombok.Getter; + +import java.util.Map; + +@Getter +public class OAuthAttributes { + private final String providerId; + private final OAuth2UserInfo oAuth2UserInfo; + + @Builder + public OAuthAttributes(String providerId, OAuth2UserInfo oAuth2UserInfo) { + this.providerId = providerId; + this.oAuth2UserInfo = oAuth2UserInfo; + } + + public static OAuthAttributes of(String provider, + String providerId, + Map attributes) { + System.out.println(providerId); + if (provider.equals(ProviderType.GOOGLE.getProvider())) { + return ofGoogle(providerId, attributes); + }else if(provider.equals(ProviderType.KAKAO.getProvider())){ + return ofKakao(providerId, attributes); + }else if(provider.equals(ProviderType.NAVER.getProvider())){ + return ofNaver(providerId, attributes); + } + throw new CustomException(ExceptionCode.PROVIDER_NOT_FOUND); + } + + private static OAuthAttributes ofGoogle(String providerId, + Map attributes) { + return OAuthAttributes.builder() + .providerId(providerId) + .oAuth2UserInfo(new GoogleUserInfo(attributes)) + .build(); + } + + private static OAuthAttributes ofKakao(String providerId, + Map attributes) { + return OAuthAttributes.builder() + .providerId(providerId) + .oAuth2UserInfo(new KakaoUserInfo(attributes)) + .build(); + } + + private static OAuthAttributes ofNaver(String providerId, + Map attributes) { + return OAuthAttributes.builder() + .providerId(providerId) + .oAuth2UserInfo(new KakaoUserInfo(attributes)) + .build(); + } + +// public User toEntity(OAuth2UserInfo oAuth2UserInfo, +// String username, +// String provider, +// PasswordEncoder passwordEncoder) { +// return new User( +// passwordEncoder.encode("OAUTH" + UUID.randomUUID()), +// username, +// oAuth2UserInfo.getEmail(), +// Collections.singletonList("ROLE_USER"), +// provider, +// oAuth2UserInfo.getProviderId() +// ); +// } +} diff --git a/src/main/java/com/tgd/trip/global/oauth2/util/UserPrincipal.java b/src/main/java/com/tgd/trip/global/oauth2/util/UserPrincipal.java new file mode 100644 index 0000000..20f8814 --- /dev/null +++ b/src/main/java/com/tgd/trip/global/oauth2/util/UserPrincipal.java @@ -0,0 +1,81 @@ +package com.tgd.trip.global.oauth2.util; + +import com.tgd.trip.user.domain.User; +import com.tgd.trip.util.AuthorityUtils; +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.user.OAuth2User; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +@Getter +public class UserPrincipal implements UserDetails, OAuth2User { + + private final User user; + private Map attributes; + + public UserPrincipal(User user) { + this.user = user; + } + + public UserPrincipal(User user, Map attributes) { + this.user = user; + this.attributes = attributes; + } + + public static UserPrincipal of(User user) { + return new UserPrincipal(user); + } + + public static UserPrincipal of(User user, Map attributes) { + return new UserPrincipal(user, attributes); + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Collection getAuthorities() { + return AuthorityUtils.getAuthorities(List.of(user.getRoles().toString())); + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public String getUsername() { + return user.getEmail(); + } + + @Override + public String getName() { + return attributes.get(user.getProviderId()).toString(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} From 712bbcc70edc0636fe64c8ed501aca04c21b7482 Mon Sep 17 00:00:00 2001 From: wjstmdduf Date: Mon, 20 Nov 2023 10:24:40 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix=20:=20role=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/tgd/trip/user/domain/User.java | 1 + src/main/java/com/tgd/trip/user/service/UserService.java | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tgd/trip/user/domain/User.java b/src/main/java/com/tgd/trip/user/domain/User.java index 1bcbab8..c977c64 100644 --- a/src/main/java/com/tgd/trip/user/domain/User.java +++ b/src/main/java/com/tgd/trip/user/domain/User.java @@ -28,6 +28,7 @@ public class User extends BaseEntity { private String email; @NotNull @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "USER_ROLES", joinColumns = @JoinColumn(name = "USER_ID")) private List roles = new ArrayList<>(); private String provider; private String providerId; diff --git a/src/main/java/com/tgd/trip/user/service/UserService.java b/src/main/java/com/tgd/trip/user/service/UserService.java index 54657c3..f66a1cf 100644 --- a/src/main/java/com/tgd/trip/user/service/UserService.java +++ b/src/main/java/com/tgd/trip/user/service/UserService.java @@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -46,7 +47,8 @@ public String postSignup(SignupDto user) { oldUser.setNickName(user.getNickName()); oldUser.setBirth(user.getBirth()); oldUser.setSex(user.getSex()); - oldUser.setRoles(List.of(Role.USER.name())); + + oldUser.getRoles().add(Role.USER.name()); System.out.println(oldUser); userRepository.save(oldUser);