From b1cb6a5a2aec9e8494c4342d086aba0712d93a39 Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Fri, 1 Nov 2024 22:52:50 +0900 Subject: [PATCH 1/8] update backlog tasks at readme.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1e7ba652..8a5776b6 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ # spring-security-authentication +## ID-PW 기반 로그인 구현 +## Basic 인증 구현 +## 인터셉터 분리 +## 인증 로직 - 서비스 로직 간 패키지 분리:wq From be0c2efaff658765c2149c233ced10c8385eee00 Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Sun, 3 Nov 2024 12:44:28 +0900 Subject: [PATCH 2/8] implement username-password based login --- build.gradle | 1 + .../nextstep/app/config/SecurityConfig.java | 27 +++++++++++++++++++ .../java/nextstep/app/ui/LoginController.java | 23 +++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/main/java/nextstep/app/config/SecurityConfig.java diff --git a/build.gradle b/build.gradle index 99766160..aae46e10 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-security' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/src/main/java/nextstep/app/config/SecurityConfig.java b/src/main/java/nextstep/app/config/SecurityConfig.java new file mode 100644 index 00000000..68f6dc4e --- /dev/null +++ b/src/main/java/nextstep/app/config/SecurityConfig.java @@ -0,0 +1,27 @@ +package nextstep.app.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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf().disable() // CSRF 비활성화 (테스트 용도) + .authorizeRequests() + .antMatchers("/login").permitAll() // /login 경로는 인증 없이 접근 허용 + .anyRequest().authenticated(); // 그 외의 요청은 인증 필요 + return http.build(); + } +} diff --git a/src/main/java/nextstep/app/ui/LoginController.java b/src/main/java/nextstep/app/ui/LoginController.java index 0ea94f1b..5b947956 100644 --- a/src/main/java/nextstep/app/ui/LoginController.java +++ b/src/main/java/nextstep/app/ui/LoginController.java @@ -1,6 +1,8 @@ package nextstep.app.ui; +import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; +import nextstep.app.infrastructure.InmemoryMemberRepository; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -12,6 +14,8 @@ @RestController public class LoginController { + private static final Member TEST_MEMBER = InmemoryMemberRepository.TEST_MEMBER_1; + public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; private final MemberRepository memberRepository; @@ -21,7 +25,24 @@ public LoginController(MemberRepository memberRepository) { } @PostMapping("/login") - public ResponseEntity login(HttpServletRequest request, HttpSession session) { + public ResponseEntity login(HttpServletRequest request, HttpSession session) throws AuthenticationException { + String name = request.getParameter("username"); + String password = request.getParameter("password"); + + // 1. 사용자 정보 조회 + Member member = memberRepository.findByEmail(name).orElseThrow(AuthenticationException::new); + + // 2. 비밀번호 확인 + if (!password.equals(member.getPassword())) { + // System.out.println("비밀번호 불일치"+password+member.getPassword()); + System.out.println("비밀번호 불일치"); + throw new AuthenticationException(); + } + + // 3. 세션에 인증 정보 저장 + session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, member); + System.out.println("인증 정보 저장"); + return ResponseEntity.ok().build(); } From e650ebcd22c747fd6b7e680d5e5e1493c56ad39b Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Sun, 3 Nov 2024 13:40:59 +0900 Subject: [PATCH 3/8] implement basic auth --- .../nextstep/app/config/SecurityConfig.java | 2 +- .../nextstep/app/ui/MemberController.java | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/main/java/nextstep/app/config/SecurityConfig.java b/src/main/java/nextstep/app/config/SecurityConfig.java index 68f6dc4e..58d8d84c 100644 --- a/src/main/java/nextstep/app/config/SecurityConfig.java +++ b/src/main/java/nextstep/app/config/SecurityConfig.java @@ -20,7 +20,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti http .csrf().disable() // CSRF 비활성화 (테스트 용도) .authorizeRequests() - .antMatchers("/login").permitAll() // /login 경로는 인증 없이 접근 허용 + .antMatchers("/login", "/members").permitAll() // /login 경로는 인증 없이 접근 허용 .anyRequest().authenticated(); // 그 외의 요청은 인증 필요 return http.build(); } diff --git a/src/main/java/nextstep/app/ui/MemberController.java b/src/main/java/nextstep/app/ui/MemberController.java index c8cc74d6..c7e38658 100644 --- a/src/main/java/nextstep/app/ui/MemberController.java +++ b/src/main/java/nextstep/app/ui/MemberController.java @@ -2,11 +2,19 @@ import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.List; +import java.util.Optional; + +import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; @RestController public class MemberController { @@ -18,7 +26,41 @@ public MemberController(MemberRepository memberRepository) { } @GetMapping("/members") - public ResponseEntity> list() { + public ResponseEntity> list(HttpServletRequest request, HttpSession session) { + // 1. 권한 확인 - Member로 등록된 사용자인지 확인 및 Session 저장 + String authHeader = request.getHeader("Authorization"); + + if (authHeader != null && authHeader.startsWith("Basic ")) { + String base64Credentials = authHeader.substring("Basic ".length()).trim(); + String credentials = new String(Base64.getDecoder().decode(base64Credentials), StandardCharsets.UTF_8); + if (!credentials.contains(":")) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + final String[] values = credentials.split(":", 2); + String username = values[0]; + String password = values[1]; + + // 1-1. 사용자 정보 조회 + Optional memberOptional = memberRepository.findByEmail(username); + if (memberOptional.isPresent()) { + Member member = memberOptional.get(); + + // 1-2. 비밀번호 확인 + if (password.equals(member.getPassword())) { + // 1-3. 세션에 인증 정보 저장 + session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, member); + } else { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + } else { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + } else { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + // 2. Member 목록 조회 List members = memberRepository.findAll(); return ResponseEntity.ok(members); } From 9571caa18b62e085f2f6dfba43b1dc907c6bfa1f Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Sun, 3 Nov 2024 14:11:46 +0900 Subject: [PATCH 4/8] implemente interceptor --- .../java/nextstep/app/config/WebConfig.java | 30 +++++++++ .../app/interceptor/BasicAuthInterceptor.java | 62 +++++++++++++++++++ .../app/interceptor/LoginInterceptor.java | 49 +++++++++++++++ .../java/nextstep/app/ui/LoginController.java | 24 +------ .../nextstep/app/ui/MemberController.java | 44 +------------ 5 files changed, 143 insertions(+), 66 deletions(-) create mode 100644 src/main/java/nextstep/app/config/WebConfig.java create mode 100644 src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java create mode 100644 src/main/java/nextstep/app/interceptor/LoginInterceptor.java diff --git a/src/main/java/nextstep/app/config/WebConfig.java b/src/main/java/nextstep/app/config/WebConfig.java new file mode 100644 index 00000000..db048b2f --- /dev/null +++ b/src/main/java/nextstep/app/config/WebConfig.java @@ -0,0 +1,30 @@ +package nextstep.app.config; + +import nextstep.app.interceptor.BasicAuthInterceptor; +import nextstep.app.interceptor.LoginInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + private final LoginInterceptor loginInterceptor; + private final BasicAuthInterceptor basicAuthInterceptor; + + @Autowired + public WebConfig(LoginInterceptor loginInterceptor, BasicAuthInterceptor basicAuthInterceptor) { + this.loginInterceptor = loginInterceptor; + this.basicAuthInterceptor = basicAuthInterceptor; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loginInterceptor) + .addPathPatterns("/login"); // ID/비밀번호 인증에 대한 경로 + registry.addInterceptor(basicAuthInterceptor) + .addPathPatterns("/members"); // Basic 인증에 대한 경로 + } +} diff --git a/src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java b/src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java new file mode 100644 index 00000000..05a8df61 --- /dev/null +++ b/src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java @@ -0,0 +1,62 @@ +package nextstep.app.interceptor; + +import nextstep.app.domain.Member; +import nextstep.app.domain.MemberRepository; +import nextstep.app.ui.AuthenticationException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Optional; + +import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; + +@Component +public class BasicAuthInterceptor implements HandlerInterceptor { + + private final MemberRepository memberRepository; + + public BasicAuthInterceptor(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + System.out.println("베이직 인터셉터"); + String authHeader = request.getHeader("Authorization"); + if (!(authHeader != null && authHeader.startsWith("Basic "))) { // invalid header + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + String base64Credentials = authHeader.substring("Basic ".length()).trim(); + String credentials = new String(Base64.getDecoder().decode(base64Credentials), StandardCharsets.UTF_8); + if (!credentials.contains(":")) { // invalid header + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + final String[] values = credentials.split(":", 2); + String username = values[0]; + String password = values[1]; + Optional memberOptional = memberRepository.findByEmail(username); + if (memberOptional.isPresent()) { + Member member = memberOptional.get(); + + // 1-2. 비밀번호 확인 + if (password.equals(member.getPassword())) { + // 1-3. 세션에 인증 정보 저장 + HttpSession session = request.getSession(); + session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, member); + return true; + } + } + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; // 다음으로 요청을 진행 + } +} diff --git a/src/main/java/nextstep/app/interceptor/LoginInterceptor.java b/src/main/java/nextstep/app/interceptor/LoginInterceptor.java new file mode 100644 index 00000000..7b59d70f --- /dev/null +++ b/src/main/java/nextstep/app/interceptor/LoginInterceptor.java @@ -0,0 +1,49 @@ +package nextstep.app.interceptor; + +import nextstep.app.domain.Member; +import nextstep.app.domain.MemberRepository; +import nextstep.app.ui.AuthenticationException; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; + +@Component +public class LoginInterceptor implements HandlerInterceptor { + + private final MemberRepository memberRepository; + + public LoginInterceptor(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + System.out.println("로그인 인터셉터"); + String username = request.getParameter("username"); + String password = request.getParameter("password"); + + if (username == null || password == null) { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + Member member = memberRepository.findByEmail(username) + .orElseThrow(AuthenticationException::new); + + if (!password.equals(member.getPassword())) { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + // 세션에 인증 정보 저장 + HttpSession session = request.getSession(); + session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, member); + + return true; // 다음으로 요청을 진행 + } +} diff --git a/src/main/java/nextstep/app/ui/LoginController.java b/src/main/java/nextstep/app/ui/LoginController.java index 5b947956..413fc9f7 100644 --- a/src/main/java/nextstep/app/ui/LoginController.java +++ b/src/main/java/nextstep/app/ui/LoginController.java @@ -9,13 +9,8 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - @RestController public class LoginController { - private static final Member TEST_MEMBER = InmemoryMemberRepository.TEST_MEMBER_1; - public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; private final MemberRepository memberRepository; @@ -25,24 +20,7 @@ public LoginController(MemberRepository memberRepository) { } @PostMapping("/login") - public ResponseEntity login(HttpServletRequest request, HttpSession session) throws AuthenticationException { - String name = request.getParameter("username"); - String password = request.getParameter("password"); - - // 1. 사용자 정보 조회 - Member member = memberRepository.findByEmail(name).orElseThrow(AuthenticationException::new); - - // 2. 비밀번호 확인 - if (!password.equals(member.getPassword())) { - // System.out.println("비밀번호 불일치"+password+member.getPassword()); - System.out.println("비밀번호 불일치"); - throw new AuthenticationException(); - } - - // 3. 세션에 인증 정보 저장 - session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, member); - System.out.println("인증 정보 저장"); - + public ResponseEntity login() throws AuthenticationException { return ResponseEntity.ok().build(); } diff --git a/src/main/java/nextstep/app/ui/MemberController.java b/src/main/java/nextstep/app/ui/MemberController.java index c7e38658..c8cc74d6 100644 --- a/src/main/java/nextstep/app/ui/MemberController.java +++ b/src/main/java/nextstep/app/ui/MemberController.java @@ -2,19 +2,11 @@ import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import java.nio.charset.StandardCharsets; -import java.util.Base64; import java.util.List; -import java.util.Optional; - -import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; @RestController public class MemberController { @@ -26,41 +18,7 @@ public MemberController(MemberRepository memberRepository) { } @GetMapping("/members") - public ResponseEntity> list(HttpServletRequest request, HttpSession session) { - // 1. 권한 확인 - Member로 등록된 사용자인지 확인 및 Session 저장 - String authHeader = request.getHeader("Authorization"); - - if (authHeader != null && authHeader.startsWith("Basic ")) { - String base64Credentials = authHeader.substring("Basic ".length()).trim(); - String credentials = new String(Base64.getDecoder().decode(base64Credentials), StandardCharsets.UTF_8); - if (!credentials.contains(":")) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - - final String[] values = credentials.split(":", 2); - String username = values[0]; - String password = values[1]; - - // 1-1. 사용자 정보 조회 - Optional memberOptional = memberRepository.findByEmail(username); - if (memberOptional.isPresent()) { - Member member = memberOptional.get(); - - // 1-2. 비밀번호 확인 - if (password.equals(member.getPassword())) { - // 1-3. 세션에 인증 정보 저장 - session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, member); - } else { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - } else { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - } else { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - - // 2. Member 목록 조회 + public ResponseEntity> list() { List members = memberRepository.findAll(); return ResponseEntity.ok(members); } From 8cb742a425135f53f723b41bccc62313b06fda48 Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Sun, 3 Nov 2024 14:41:14 +0900 Subject: [PATCH 5/8] separate authentication logic and service logic --- .../SecurityAuthenticationApplication.java | 2 ++ .../java/nextstep/app/config/WebConfig.java | 4 +-- .../java/nextstep/app/ui/LoginController.java | 5 +-- .../nextstep/security/SecurityConstants.java | 5 +++ .../java/nextstep/security/dto/MemberDTO.java | 31 +++++++++++++++++++ .../exception}/AuthenticationException.java | 2 +- .../interceptor/BasicAuthInterceptor.java | 8 ++--- .../interceptor/LoginInterceptor.java | 6 ++-- 8 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 src/main/java/nextstep/security/SecurityConstants.java create mode 100644 src/main/java/nextstep/security/dto/MemberDTO.java rename src/main/java/nextstep/{app/ui => security/exception}/AuthenticationException.java (64%) rename src/main/java/nextstep/{app => security}/interceptor/BasicAuthInterceptor.java (90%) rename src/main/java/nextstep/{app => security}/interceptor/LoginInterceptor.java (89%) diff --git a/src/main/java/nextstep/app/SecurityAuthenticationApplication.java b/src/main/java/nextstep/app/SecurityAuthenticationApplication.java index 0f8eb47d..7dea1d7d 100644 --- a/src/main/java/nextstep/app/SecurityAuthenticationApplication.java +++ b/src/main/java/nextstep/app/SecurityAuthenticationApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; @SpringBootApplication +@ComponentScan(basePackages = {"nextstep.app", "nextstep.security"}) public class SecurityAuthenticationApplication { public static void main(String[] args) { diff --git a/src/main/java/nextstep/app/config/WebConfig.java b/src/main/java/nextstep/app/config/WebConfig.java index db048b2f..c902536f 100644 --- a/src/main/java/nextstep/app/config/WebConfig.java +++ b/src/main/java/nextstep/app/config/WebConfig.java @@ -1,7 +1,7 @@ package nextstep.app.config; -import nextstep.app.interceptor.BasicAuthInterceptor; -import nextstep.app.interceptor.LoginInterceptor; +import nextstep.security.interceptor.BasicAuthInterceptor; +import nextstep.security.interceptor.LoginInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; diff --git a/src/main/java/nextstep/app/ui/LoginController.java b/src/main/java/nextstep/app/ui/LoginController.java index 413fc9f7..775851f2 100644 --- a/src/main/java/nextstep/app/ui/LoginController.java +++ b/src/main/java/nextstep/app/ui/LoginController.java @@ -1,8 +1,7 @@ package nextstep.app.ui; -import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; -import nextstep.app.infrastructure.InmemoryMemberRepository; +import nextstep.security.exception.AuthenticationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -11,8 +10,6 @@ @RestController public class LoginController { - public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; - private final MemberRepository memberRepository; public LoginController(MemberRepository memberRepository) { diff --git a/src/main/java/nextstep/security/SecurityConstants.java b/src/main/java/nextstep/security/SecurityConstants.java new file mode 100644 index 00000000..779bc5ab --- /dev/null +++ b/src/main/java/nextstep/security/SecurityConstants.java @@ -0,0 +1,5 @@ +package nextstep.security; + +public class SecurityConstants { + public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; +} diff --git a/src/main/java/nextstep/security/dto/MemberDTO.java b/src/main/java/nextstep/security/dto/MemberDTO.java new file mode 100644 index 00000000..4ffeab84 --- /dev/null +++ b/src/main/java/nextstep/security/dto/MemberDTO.java @@ -0,0 +1,31 @@ +package nextstep.security.dto; + +public class MemberDTO { + private final String email; + private final String password; + private final String name; + private final String imageUrl; + + public MemberDTO(String email, String password, String name, String imageUrl) { + this.email = email; + this.password = password; + this.name = name; + this.imageUrl = imageUrl; + } + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } + + public String getName() { + return name; + } + + public String getImageUrl() { + return imageUrl; + } +} diff --git a/src/main/java/nextstep/app/ui/AuthenticationException.java b/src/main/java/nextstep/security/exception/AuthenticationException.java similarity index 64% rename from src/main/java/nextstep/app/ui/AuthenticationException.java rename to src/main/java/nextstep/security/exception/AuthenticationException.java index f809b6e4..1271b52d 100644 --- a/src/main/java/nextstep/app/ui/AuthenticationException.java +++ b/src/main/java/nextstep/security/exception/AuthenticationException.java @@ -1,4 +1,4 @@ -package nextstep.app.ui; +package nextstep.security.exception; public class AuthenticationException extends RuntimeException { } diff --git a/src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java b/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java similarity index 90% rename from src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java rename to src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java index 05a8df61..a6fec26a 100644 --- a/src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java +++ b/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java @@ -1,10 +1,8 @@ -package nextstep.app.interceptor; +package nextstep.security.interceptor; import nextstep.app.domain.Member; +import nextstep.security.dto.MemberDTO; import nextstep.app.domain.MemberRepository; -import nextstep.app.ui.AuthenticationException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @@ -15,7 +13,7 @@ import java.util.Base64; import java.util.Optional; -import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; +import static nextstep.security.SecurityConstants.SPRING_SECURITY_CONTEXT_KEY; @Component public class BasicAuthInterceptor implements HandlerInterceptor { diff --git a/src/main/java/nextstep/app/interceptor/LoginInterceptor.java b/src/main/java/nextstep/security/interceptor/LoginInterceptor.java similarity index 89% rename from src/main/java/nextstep/app/interceptor/LoginInterceptor.java rename to src/main/java/nextstep/security/interceptor/LoginInterceptor.java index 7b59d70f..d0c55d4c 100644 --- a/src/main/java/nextstep/app/interceptor/LoginInterceptor.java +++ b/src/main/java/nextstep/security/interceptor/LoginInterceptor.java @@ -1,8 +1,8 @@ -package nextstep.app.interceptor; +package nextstep.security.interceptor; import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; -import nextstep.app.ui.AuthenticationException; +import nextstep.security.exception.AuthenticationException; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @@ -10,7 +10,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; +import static nextstep.security.SecurityConstants.SPRING_SECURITY_CONTEXT_KEY; @Component public class LoginInterceptor implements HandlerInterceptor { From e6f23376cc6a9b7d9965b53d98efb67c02ce3001 Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Sun, 3 Nov 2024 14:41:14 +0900 Subject: [PATCH 6/8] separate authentication logic and service logic --- .../nextstep/app/SecurityAuthenticationApplication.java | 2 ++ src/main/java/nextstep/app/config/WebConfig.java | 4 ++-- src/main/java/nextstep/app/ui/LoginController.java | 5 +---- src/main/java/nextstep/security/SecurityConstants.java | 5 +++++ .../ui => security/exception}/AuthenticationException.java | 2 +- .../interceptor/BasicAuthInterceptor.java | 7 ++----- .../{app => security}/interceptor/LoginInterceptor.java | 6 +++--- 7 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 src/main/java/nextstep/security/SecurityConstants.java rename src/main/java/nextstep/{app/ui => security/exception}/AuthenticationException.java (64%) rename src/main/java/nextstep/{app => security}/interceptor/BasicAuthInterceptor.java (90%) rename src/main/java/nextstep/{app => security}/interceptor/LoginInterceptor.java (89%) diff --git a/src/main/java/nextstep/app/SecurityAuthenticationApplication.java b/src/main/java/nextstep/app/SecurityAuthenticationApplication.java index 0f8eb47d..7dea1d7d 100644 --- a/src/main/java/nextstep/app/SecurityAuthenticationApplication.java +++ b/src/main/java/nextstep/app/SecurityAuthenticationApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; @SpringBootApplication +@ComponentScan(basePackages = {"nextstep.app", "nextstep.security"}) public class SecurityAuthenticationApplication { public static void main(String[] args) { diff --git a/src/main/java/nextstep/app/config/WebConfig.java b/src/main/java/nextstep/app/config/WebConfig.java index db048b2f..c902536f 100644 --- a/src/main/java/nextstep/app/config/WebConfig.java +++ b/src/main/java/nextstep/app/config/WebConfig.java @@ -1,7 +1,7 @@ package nextstep.app.config; -import nextstep.app.interceptor.BasicAuthInterceptor; -import nextstep.app.interceptor.LoginInterceptor; +import nextstep.security.interceptor.BasicAuthInterceptor; +import nextstep.security.interceptor.LoginInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; diff --git a/src/main/java/nextstep/app/ui/LoginController.java b/src/main/java/nextstep/app/ui/LoginController.java index 413fc9f7..775851f2 100644 --- a/src/main/java/nextstep/app/ui/LoginController.java +++ b/src/main/java/nextstep/app/ui/LoginController.java @@ -1,8 +1,7 @@ package nextstep.app.ui; -import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; -import nextstep.app.infrastructure.InmemoryMemberRepository; +import nextstep.security.exception.AuthenticationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -11,8 +10,6 @@ @RestController public class LoginController { - public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; - private final MemberRepository memberRepository; public LoginController(MemberRepository memberRepository) { diff --git a/src/main/java/nextstep/security/SecurityConstants.java b/src/main/java/nextstep/security/SecurityConstants.java new file mode 100644 index 00000000..779bc5ab --- /dev/null +++ b/src/main/java/nextstep/security/SecurityConstants.java @@ -0,0 +1,5 @@ +package nextstep.security; + +public class SecurityConstants { + public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; +} diff --git a/src/main/java/nextstep/app/ui/AuthenticationException.java b/src/main/java/nextstep/security/exception/AuthenticationException.java similarity index 64% rename from src/main/java/nextstep/app/ui/AuthenticationException.java rename to src/main/java/nextstep/security/exception/AuthenticationException.java index f809b6e4..1271b52d 100644 --- a/src/main/java/nextstep/app/ui/AuthenticationException.java +++ b/src/main/java/nextstep/security/exception/AuthenticationException.java @@ -1,4 +1,4 @@ -package nextstep.app.ui; +package nextstep.security.exception; public class AuthenticationException extends RuntimeException { } diff --git a/src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java b/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java similarity index 90% rename from src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java rename to src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java index 05a8df61..2d332cc5 100644 --- a/src/main/java/nextstep/app/interceptor/BasicAuthInterceptor.java +++ b/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java @@ -1,10 +1,7 @@ -package nextstep.app.interceptor; +package nextstep.security.interceptor; import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; -import nextstep.app.ui.AuthenticationException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @@ -15,7 +12,7 @@ import java.util.Base64; import java.util.Optional; -import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; +import static nextstep.security.SecurityConstants.SPRING_SECURITY_CONTEXT_KEY; @Component public class BasicAuthInterceptor implements HandlerInterceptor { diff --git a/src/main/java/nextstep/app/interceptor/LoginInterceptor.java b/src/main/java/nextstep/security/interceptor/LoginInterceptor.java similarity index 89% rename from src/main/java/nextstep/app/interceptor/LoginInterceptor.java rename to src/main/java/nextstep/security/interceptor/LoginInterceptor.java index 7b59d70f..d0c55d4c 100644 --- a/src/main/java/nextstep/app/interceptor/LoginInterceptor.java +++ b/src/main/java/nextstep/security/interceptor/LoginInterceptor.java @@ -1,8 +1,8 @@ -package nextstep.app.interceptor; +package nextstep.security.interceptor; import nextstep.app.domain.Member; import nextstep.app.domain.MemberRepository; -import nextstep.app.ui.AuthenticationException; +import nextstep.security.exception.AuthenticationException; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @@ -10,7 +10,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import static nextstep.app.ui.LoginController.SPRING_SECURITY_CONTEXT_KEY; +import static nextstep.security.SecurityConstants.SPRING_SECURITY_CONTEXT_KEY; @Component public class LoginInterceptor implements HandlerInterceptor { From e9467e7803250ada34c90e2870804f1d08490e47 Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Sun, 3 Nov 2024 15:13:46 +0900 Subject: [PATCH 7/8] change bidirectional references between app & security packages to unidirectional references --- .../nextstep/app/infrastructure/InmemoryMemberRepository.java | 2 +- src/main/java/nextstep/app/ui/LoginController.java | 2 +- src/main/java/nextstep/app/ui/MemberController.java | 2 +- .../nextstep/security/interceptor/BasicAuthInterceptor.java | 2 +- .../java/nextstep/security/interceptor/LoginInterceptor.java | 2 +- .../{app/domain => security/service}/MemberRepository.java | 4 +++- src/test/java/nextstep/app/MemberTest.java | 2 +- 7 files changed, 9 insertions(+), 7 deletions(-) rename src/main/java/nextstep/{app/domain => security/service}/MemberRepository.java (73%) diff --git a/src/main/java/nextstep/app/infrastructure/InmemoryMemberRepository.java b/src/main/java/nextstep/app/infrastructure/InmemoryMemberRepository.java index 5a6062cf..881c55d6 100644 --- a/src/main/java/nextstep/app/infrastructure/InmemoryMemberRepository.java +++ b/src/main/java/nextstep/app/infrastructure/InmemoryMemberRepository.java @@ -1,7 +1,7 @@ package nextstep.app.infrastructure; import nextstep.app.domain.Member; -import nextstep.app.domain.MemberRepository; +import nextstep.security.service.MemberRepository; import org.springframework.stereotype.Repository; import java.util.HashMap; diff --git a/src/main/java/nextstep/app/ui/LoginController.java b/src/main/java/nextstep/app/ui/LoginController.java index 775851f2..1de15c32 100644 --- a/src/main/java/nextstep/app/ui/LoginController.java +++ b/src/main/java/nextstep/app/ui/LoginController.java @@ -1,6 +1,6 @@ package nextstep.app.ui; -import nextstep.app.domain.MemberRepository; +import nextstep.security.service.MemberRepository; import nextstep.security.exception.AuthenticationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/nextstep/app/ui/MemberController.java b/src/main/java/nextstep/app/ui/MemberController.java index c8cc74d6..2d4caf8c 100644 --- a/src/main/java/nextstep/app/ui/MemberController.java +++ b/src/main/java/nextstep/app/ui/MemberController.java @@ -1,7 +1,7 @@ package nextstep.app.ui; import nextstep.app.domain.Member; -import nextstep.app.domain.MemberRepository; +import nextstep.security.service.MemberRepository; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java b/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java index 2d332cc5..845f1d05 100644 --- a/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java +++ b/src/main/java/nextstep/security/interceptor/BasicAuthInterceptor.java @@ -1,7 +1,7 @@ package nextstep.security.interceptor; import nextstep.app.domain.Member; -import nextstep.app.domain.MemberRepository; +import nextstep.security.service.MemberRepository; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; diff --git a/src/main/java/nextstep/security/interceptor/LoginInterceptor.java b/src/main/java/nextstep/security/interceptor/LoginInterceptor.java index d0c55d4c..0af12625 100644 --- a/src/main/java/nextstep/security/interceptor/LoginInterceptor.java +++ b/src/main/java/nextstep/security/interceptor/LoginInterceptor.java @@ -1,7 +1,7 @@ package nextstep.security.interceptor; import nextstep.app.domain.Member; -import nextstep.app.domain.MemberRepository; +import nextstep.security.service.MemberRepository; import nextstep.security.exception.AuthenticationException; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; diff --git a/src/main/java/nextstep/app/domain/MemberRepository.java b/src/main/java/nextstep/security/service/MemberRepository.java similarity index 73% rename from src/main/java/nextstep/app/domain/MemberRepository.java rename to src/main/java/nextstep/security/service/MemberRepository.java index 2eb5cdbb..c2f30e54 100644 --- a/src/main/java/nextstep/app/domain/MemberRepository.java +++ b/src/main/java/nextstep/security/service/MemberRepository.java @@ -1,4 +1,6 @@ -package nextstep.app.domain; +package nextstep.security.service; + +import nextstep.app.domain.Member; import java.util.List; import java.util.Optional; diff --git a/src/test/java/nextstep/app/MemberTest.java b/src/test/java/nextstep/app/MemberTest.java index 58aba17b..ceea5b1f 100644 --- a/src/test/java/nextstep/app/MemberTest.java +++ b/src/test/java/nextstep/app/MemberTest.java @@ -1,7 +1,7 @@ package nextstep.app; import nextstep.app.domain.Member; -import nextstep.app.domain.MemberRepository; +import nextstep.security.service.MemberRepository; import nextstep.app.infrastructure.InmemoryMemberRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; From 3820e6667c44eefe03376f3b5740678cb26c3989 Mon Sep 17 00:00:00 2001 From: Seyoung9304 Date: Sun, 3 Nov 2024 15:18:57 +0900 Subject: [PATCH 8/8] remove redundant file --- .../java/nextstep/security/dto/MemberDTO.java | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 src/main/java/nextstep/security/dto/MemberDTO.java diff --git a/src/main/java/nextstep/security/dto/MemberDTO.java b/src/main/java/nextstep/security/dto/MemberDTO.java deleted file mode 100644 index 4ffeab84..00000000 --- a/src/main/java/nextstep/security/dto/MemberDTO.java +++ /dev/null @@ -1,31 +0,0 @@ -package nextstep.security.dto; - -public class MemberDTO { - private final String email; - private final String password; - private final String name; - private final String imageUrl; - - public MemberDTO(String email, String password, String name, String imageUrl) { - this.email = email; - this.password = password; - this.name = name; - this.imageUrl = imageUrl; - } - - public String getEmail() { - return email; - } - - public String getPassword() { - return password; - } - - public String getName() { - return name; - } - - public String getImageUrl() { - return imageUrl; - } -}