From 559881bb44270b31e53036589bd433c5fb3b1334 Mon Sep 17 00:00:00 2001 From: Gyaak Date: Fri, 2 Aug 2024 16:31:41 +0900 Subject: [PATCH] =?UTF-8?q?[FIX]=20=EB=84=A4=EC=9D=B4=EB=B2=84=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EA=B5=AC=ED=98=84=20=EB=88=84=EB=9D=BD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20#9=20(#32)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OAuth관련 코드가 누락된 부분이 있어 다시 올립니다. --- .../talkka/server/config/SecurityConfig.java | 34 +++++++++++ .../oauth/OAuth2LoginFailureHandler.java | 23 ++++++- .../oauth/OAuth2LoginSuccessHandler.java | 30 ++++++++- .../oauth/controller/AuthController.java | 61 +++++++++++++++++++ .../server/oauth/domain/AuthUserDto.java | 14 +++++ .../oauth/domain/CustomUserPrincipal.java | 32 +++++++++- .../oauth/service/CustomOAuth2Service.java | 44 ++++++++++++- server/src/main/resources/static/index.html | 10 +++ .../main/resources/templates/loginForm.html | 11 ++++ .../main/resources/templates/signUpForm.html | 51 ++++++++++++++++ 10 files changed, 306 insertions(+), 4 deletions(-) create mode 100644 server/src/main/resources/static/index.html create mode 100644 server/src/main/resources/templates/loginForm.html create mode 100644 server/src/main/resources/templates/signUpForm.html diff --git a/server/src/main/java/com/talkka/server/config/SecurityConfig.java b/server/src/main/java/com/talkka/server/config/SecurityConfig.java index 2842e94d..561bcca8 100644 --- a/server/src/main/java/com/talkka/server/config/SecurityConfig.java +++ b/server/src/main/java/com/talkka/server/config/SecurityConfig.java @@ -1,4 +1,38 @@ package com.talkka.server.config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; + +import com.talkka.server.oauth.OAuth2LoginFailureHandler; +import com.talkka.server.oauth.OAuth2LoginSuccessHandler; +import com.talkka.server.oauth.service.CustomOAuth2Service; + +import lombok.RequiredArgsConstructor; + +@Configuration +@RequiredArgsConstructor public class SecurityConfig { + + private final CustomOAuth2Service customOAuth2Service; + private final OAuth2LoginSuccessHandler oAuth2LoginSuccessHandler; + private final OAuth2LoginFailureHandler oAuth2LoginFailureHandler; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(AbstractHttpConfigurer::disable) + .cors(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/auth/**").permitAll() + .anyRequest().authenticated()) + .oauth2Login(oauth -> oauth + .userInfoEndpoint(userInfo -> userInfo.userService(customOAuth2Service)) + .successHandler(oAuth2LoginSuccessHandler) + .failureHandler(oAuth2LoginFailureHandler) + ); + return http.build(); + } } diff --git a/server/src/main/java/com/talkka/server/oauth/OAuth2LoginFailureHandler.java b/server/src/main/java/com/talkka/server/oauth/OAuth2LoginFailureHandler.java index 0aeaf05c..5951e25b 100644 --- a/server/src/main/java/com/talkka/server/oauth/OAuth2LoginFailureHandler.java +++ b/server/src/main/java/com/talkka/server/oauth/OAuth2LoginFailureHandler.java @@ -1,4 +1,25 @@ package com.talkka.server.oauth; -public class OAuth2LoginFailureHandler { +import java.io.IOException; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Component +public class OAuth2LoginFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { + + request.getSession().invalidate(); + String defaultFailureUrl = "/auth/login"; + setDefaultFailureUrl(defaultFailureUrl); + super.onAuthenticationFailure(request, response, exception); + } } diff --git a/server/src/main/java/com/talkka/server/oauth/OAuth2LoginSuccessHandler.java b/server/src/main/java/com/talkka/server/oauth/OAuth2LoginSuccessHandler.java index 6b15d843..333fb68a 100644 --- a/server/src/main/java/com/talkka/server/oauth/OAuth2LoginSuccessHandler.java +++ b/server/src/main/java/com/talkka/server/oauth/OAuth2LoginSuccessHandler.java @@ -1,4 +1,32 @@ package com.talkka.server.oauth; -public class OAuth2LoginSuccessHandler { +import java.io.IOException; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import com.talkka.server.oauth.domain.AuthUserDto; +import com.talkka.server.oauth.domain.CustomUserPrincipal; +import com.talkka.server.user.service.UserService; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class OAuth2LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { + + private final UserService userService; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException, ServletException { + AuthUserDto userDto = ((CustomUserPrincipal)authentication.getPrincipal()).getUser(); + if (!userDto.getIsRegistered()) { + getRedirectStrategy().sendRedirect(request, response, "/auth/signUp"); + } + } } diff --git a/server/src/main/java/com/talkka/server/oauth/controller/AuthController.java b/server/src/main/java/com/talkka/server/oauth/controller/AuthController.java index dc28a824..60c6b6ff 100644 --- a/server/src/main/java/com/talkka/server/oauth/controller/AuthController.java +++ b/server/src/main/java/com/talkka/server/oauth/controller/AuthController.java @@ -1,4 +1,65 @@ package com.talkka.server.oauth.controller; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import com.talkka.server.oauth.domain.AuthUserDto; +import com.talkka.server.oauth.domain.CustomUserPrincipal; +import com.talkka.server.user.dto.UserCreateDto; +import com.talkka.server.user.dto.UserDto; +import com.talkka.server.user.service.UserService; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; + +@Controller +@RequiredArgsConstructor +@RequestMapping("/auth") public class AuthController { + + private final UserService userService; + + @GetMapping("/login") + public String loginForm() { + return "loginForm"; + } + + @GetMapping("/signUp") + public String signUpForm(Model model, @AuthenticationPrincipal CustomUserPrincipal principal) { + AuthUserDto userDto = principal.getUser(); + model.addAttribute("user", userDto); + return "signUpForm"; + } + + @SuppressWarnings("checkstyle:WhitespaceAround") + @PostMapping("/signUp") + public String signUp(@RequestParam("nickname") String nickname, + Model model, + @AuthenticationPrincipal CustomUserPrincipal principal, + HttpServletRequest request) { + if (userService.isDuplicatedNickname(nickname)) { + return "signUpForm"; + } + AuthUserDto authUserDto = principal.getUser(); + UserCreateDto userCreateDto = UserCreateDto.builder() + .name(authUserDto.getName()) + .email(authUserDto.getEmail()) + .oauthProvider(authUserDto.getProvider()) + .nickname(nickname) + .accessToken(authUserDto.getAccessToken()) + .build(); + UserDto user = userService.createUser(userCreateDto); + request.getSession().invalidate(); + return "redirect:/"; + } + + @GetMapping("/login/naver") + public String loginWithNaver() { + return "redirect:https://nid.naver.com/oauth2.0/authorize"; + } } diff --git a/server/src/main/java/com/talkka/server/oauth/domain/AuthUserDto.java b/server/src/main/java/com/talkka/server/oauth/domain/AuthUserDto.java index c832c70e..1e06e44a 100644 --- a/server/src/main/java/com/talkka/server/oauth/domain/AuthUserDto.java +++ b/server/src/main/java/com/talkka/server/oauth/domain/AuthUserDto.java @@ -1,4 +1,18 @@ package com.talkka.server.oauth.domain; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder public class AuthUserDto { + private String name; + private String email; + private String accessToken; + private String provider; + private Boolean isRegistered; } diff --git a/server/src/main/java/com/talkka/server/oauth/domain/CustomUserPrincipal.java b/server/src/main/java/com/talkka/server/oauth/domain/CustomUserPrincipal.java index 9babd035..22c1c32e 100644 --- a/server/src/main/java/com/talkka/server/oauth/domain/CustomUserPrincipal.java +++ b/server/src/main/java/com/talkka/server/oauth/domain/CustomUserPrincipal.java @@ -1,4 +1,34 @@ package com.talkka.server.oauth.domain; -public class CustomUserPrincipal { +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.core.user.OAuth2User; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class CustomUserPrincipal implements OAuth2User { + private final AuthUserDto user; + private final Map attributes; + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Collection getAuthorities() { + return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + } + + @Override + public String getName() { + return user.getName(); + } } diff --git a/server/src/main/java/com/talkka/server/oauth/service/CustomOAuth2Service.java b/server/src/main/java/com/talkka/server/oauth/service/CustomOAuth2Service.java index 674305f3..f2fda553 100644 --- a/server/src/main/java/com/talkka/server/oauth/service/CustomOAuth2Service.java +++ b/server/src/main/java/com/talkka/server/oauth/service/CustomOAuth2Service.java @@ -1,4 +1,46 @@ package com.talkka.server.oauth.service; -public class CustomOAuth2Service { +import java.util.HashMap; +import java.util.Map; + +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 com.talkka.server.oauth.domain.AuthUserDto; +import com.talkka.server.oauth.domain.CustomUserPrincipal; +import com.talkka.server.user.dao.UserRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class CustomOAuth2Service extends DefaultOAuth2UserService { + + private final UserRepository userRepository; + + @SuppressWarnings("checkstyle:RegexpSingleline") + @Override + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + OAuth2User oAuth2User = super.loadUser(userRequest); + Map tmpMap = oAuth2User.getAttribute("response"); + assert tmpMap != null; + String email = (String)tmpMap.get("email"); + String name = (String)tmpMap.get("name"); + String accessToken = userRequest.getAccessToken().getTokenValue(); + String provider = userRequest.getClientRegistration().getClientName(); + boolean isRegistered = userRepository.existsByEmail(email); + + AuthUserDto userDto = AuthUserDto.builder() + .name(name) + .email(email) + .accessToken(accessToken) + .provider(provider) + .isRegistered(isRegistered) + .build(); + + return new CustomUserPrincipal(userDto, new HashMap<>()); + } } diff --git a/server/src/main/resources/static/index.html b/server/src/main/resources/static/index.html new file mode 100644 index 00000000..b1279fec --- /dev/null +++ b/server/src/main/resources/static/index.html @@ -0,0 +1,10 @@ + + + + + Title + + +이건 홈이에요 + + \ No newline at end of file diff --git a/server/src/main/resources/templates/loginForm.html b/server/src/main/resources/templates/loginForm.html new file mode 100644 index 00000000..196c1c8d --- /dev/null +++ b/server/src/main/resources/templates/loginForm.html @@ -0,0 +1,11 @@ + + + + + 로그인페이지 + + +

로그인 페이지 입니다/

+Naver Login + + \ No newline at end of file diff --git a/server/src/main/resources/templates/signUpForm.html b/server/src/main/resources/templates/signUpForm.html new file mode 100644 index 00000000..81eff877 --- /dev/null +++ b/server/src/main/resources/templates/signUpForm.html @@ -0,0 +1,51 @@ + + + + + 회원가입 페이지 + + + +

회원가입 페이지 입니다

+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ +