From 7563fe196b993e755ee4bd1336007b7f74bedec3 Mon Sep 17 00:00:00 2001 From: guitarcode Date: Thu, 16 Feb 2023 18:18:31 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20api=20=EC=8B=9C=EB=B2=94?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84(#3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - User 도메인 클래스 개발 - Security 커스터마이징을 위한 클래스 오버라이딩 --- .DS_Store | Bin 6148 -> 6148 bytes .../blossom/dotori/config/SecurityConfig.java | 68 ++++++++++++++++++ .../blossom/dotori/config/WebMvcConfig.java | 15 ++++ .../blossom/dotori/user/AuthRequestDto.java | 9 +++ .../season/blossom/dotori/user/Authority.java | 9 +++ .../blossom/dotori/user/CustomUserDetail.java | 61 ++++++++++++++++ .../dotori/user/CustomUserDetailsService.java | 27 +++++++ .../user/JsonLoginProcessingFilter.java | 39 ++++++++++ .../java/season/blossom/dotori/user/User.java | 40 +++++++++++ .../blossom/dotori/user/UserController.java | 33 +++++++++ .../blossom/dotori/user/UserRepository.java | 9 +++ dotori/src/main/resources/application.yml | 9 +-- 12 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 dotori/src/main/java/season/blossom/dotori/config/SecurityConfig.java create mode 100644 dotori/src/main/java/season/blossom/dotori/config/WebMvcConfig.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/AuthRequestDto.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/Authority.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/CustomUserDetail.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/CustomUserDetailsService.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/JsonLoginProcessingFilter.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/User.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/UserController.java create mode 100644 dotori/src/main/java/season/blossom/dotori/user/UserRepository.java diff --git a/.DS_Store b/.DS_Store index 15a0124ce0fd59244e55c7d03a6f00b79bd576ff..41bd056153aed2002ef6b42a4cf45c6ae57ffd02 100644 GIT binary patch delta 540 zcmZoMXfc=|#>B!ku~2NHo+2aj#DLw41(=u_nJ4owKB>=4E-OgN$xmWnU_6vmkds+l zVqkDzK!A~nnT3^&or9B$n}?T=UqDbuSWrYzR8&+o9&SiTWdTr; z2$~}IqSVy9==7q@6#ule;?$A|kQK>A`8hcO`Nf$fnfZBB`mu~2NHo+2aD#DLwC4MbQb^RqnMe2&eMakBykJIlm|>zmm*_&I>; dHVblmXP(S2Vky7?1dI#}Oi-F-bA-qmW&m8S5+MKp diff --git a/dotori/src/main/java/season/blossom/dotori/config/SecurityConfig.java b/dotori/src/main/java/season/blossom/dotori/config/SecurityConfig.java new file mode 100644 index 0000000..4372c12 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/config/SecurityConfig.java @@ -0,0 +1,68 @@ +package season.blossom.dotori.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import season.blossom.dotori.user.JsonLoginProcessingFilter; + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class SecurityConfig { + + private final UserDetailsService userDetailsService; + + @Bean + AuthenticationManager authenticationManager( + AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return (web) -> web.ignoring() + .antMatchers(HttpMethod.POST, "/api/user/**"); + } + @Bean + public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { + JsonLoginProcessingFilter jsonLoginProcessingFilter = new JsonLoginProcessingFilter(); + jsonLoginProcessingFilter.setAuthenticationManager(authenticationManager); + + http.csrf().disable() + .addFilterAt(jsonLoginProcessingFilter, UsernamePasswordAuthenticationFilter.class); + + http + .authorizeRequests() + .antMatchers("/?**") + .authenticated(); + + http.authorizeRequests() + .antMatchers("/", "/api/signin", "/api/login") + .permitAll(); + + http.userDetailsService(userDetailsService); + + + return http.build(); + + } + + + @Bean + public PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); + } +} diff --git a/dotori/src/main/java/season/blossom/dotori/config/WebMvcConfig.java b/dotori/src/main/java/season/blossom/dotori/config/WebMvcConfig.java new file mode 100644 index 0000000..7811975 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/config/WebMvcConfig.java @@ -0,0 +1,15 @@ +package season.blossom.dotori.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("http://localhost:3000") + .allowedMethods("GET","POST","PUT","DELETE"); + } +} \ No newline at end of file diff --git a/dotori/src/main/java/season/blossom/dotori/user/AuthRequestDto.java b/dotori/src/main/java/season/blossom/dotori/user/AuthRequestDto.java new file mode 100644 index 0000000..68c4993 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/AuthRequestDto.java @@ -0,0 +1,9 @@ +package season.blossom.dotori.user; + +import lombok.Data; + +@Data +public class AuthRequestDto { + private String email; + private String password; +} diff --git a/dotori/src/main/java/season/blossom/dotori/user/Authority.java b/dotori/src/main/java/season/blossom/dotori/user/Authority.java new file mode 100644 index 0000000..1ac13a4 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/Authority.java @@ -0,0 +1,9 @@ +package season.blossom.dotori.user; + +import lombok.Getter; + + +@Getter +public enum Authority { + ROLE_USER, ROLE_ADMIN +} diff --git a/dotori/src/main/java/season/blossom/dotori/user/CustomUserDetail.java b/dotori/src/main/java/season/blossom/dotori/user/CustomUserDetail.java new file mode 100644 index 0000000..e3130c1 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/CustomUserDetail.java @@ -0,0 +1,61 @@ +package season.blossom.dotori.user; + +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; + +@Getter +public class CustomUserDetail implements UserDetails { + + private User user; + + public CustomUserDetail(User user) { + this.user = user; + } + + @Override + public Collection getAuthorities() { + Collection collection = new ArrayList<>(); + collection.add(new GrantedAuthority() { + @Override + public String getAuthority() { + return user.getAuthority().name(); + } + } + ); + return collection; + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public String getUsername() { + return user.getEmail(); + } + + @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/dotori/src/main/java/season/blossom/dotori/user/CustomUserDetailsService.java b/dotori/src/main/java/season/blossom/dotori/user/CustomUserDetailsService.java new file mode 100644 index 0000000..ad3eae9 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/CustomUserDetailsService.java @@ -0,0 +1,27 @@ +package season.blossom.dotori.user; + +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + + private final UserRepository userRepository; + + //시큐리티 내부의 로그인 프로세스중 인증처리를 하는 메소드 중 하나 + //이 메서드를 오버라이드하여 데이터베이스의 유저 정보 + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + User user = userRepository.findByEmail(email).orElse(null); + + if (user == null) { + throw new UsernameNotFoundException("UsernameNotFoundException"); + } + + return new CustomUserDetail(user); + } +} diff --git a/dotori/src/main/java/season/blossom/dotori/user/JsonLoginProcessingFilter.java b/dotori/src/main/java/season/blossom/dotori/user/JsonLoginProcessingFilter.java new file mode 100644 index 0000000..fe6ac0e --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/JsonLoginProcessingFilter.java @@ -0,0 +1,39 @@ +package season.blossom.dotori.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.util.StreamUtils; + +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class JsonLoginProcessingFilter extends AbstractAuthenticationProcessingFilter { + + public JsonLoginProcessingFilter() { + super(new AntPathRequestMatcher("/api/login", "POST")); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + ServletInputStream inputStream = request.getInputStream(); + String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); + + ObjectMapper mapper = new ObjectMapper(); + AuthRequestDto authRequestDto = mapper.readValue(messageBody, AuthRequestDto.class); + + UsernamePasswordAuthenticationToken authRequest = + new UsernamePasswordAuthenticationToken(authRequestDto.getEmail(), authRequestDto.getPassword()); + + return super.getAuthenticationManager().authenticate(authRequest); + + } + +} diff --git a/dotori/src/main/java/season/blossom/dotori/user/User.java b/dotori/src/main/java/season/blossom/dotori/user/User.java new file mode 100644 index 0000000..b1142d3 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/User.java @@ -0,0 +1,40 @@ +package season.blossom.dotori.user; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.persistence.*; + +@Entity +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class User { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long userId; + + private String email; + private String password; + private String name; + private Integer age; + + private Boolean calling; + private Boolean smoking; + private Boolean eating; + private Byte cleaningCycle; + private Byte floor; + private String sleepHabits; + private Byte sleepTime; + + @Enumerated(EnumType.STRING) + private Authority authority; + + public User encodePassword(PasswordEncoder passwordEncoder){ + password = passwordEncoder.encode(password); + return this; + } +} diff --git a/dotori/src/main/java/season/blossom/dotori/user/UserController.java b/dotori/src/main/java/season/blossom/dotori/user/UserController.java new file mode 100644 index 0000000..bcf35fa --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/UserController.java @@ -0,0 +1,33 @@ +package season.blossom.dotori.user; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class UserController { + + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + + @PostMapping("/api/signin") + public ResponseEntity signIn(@RequestBody AuthRequestDto authRequestDto) { + User user = User.builder() + .email(authRequestDto.getEmail()) + .password(authRequestDto.getPassword()) + .build(); + + user.encodePassword(passwordEncoder); + userRepository.save(user); + + return new ResponseEntity<>(HttpStatus.OK); + } + + + +} diff --git a/dotori/src/main/java/season/blossom/dotori/user/UserRepository.java b/dotori/src/main/java/season/blossom/dotori/user/UserRepository.java new file mode 100644 index 0000000..a1f2d52 --- /dev/null +++ b/dotori/src/main/java/season/blossom/dotori/user/UserRepository.java @@ -0,0 +1,9 @@ +package season.blossom.dotori.user; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + Optional findByEmail(String email); +} diff --git a/dotori/src/main/resources/application.yml b/dotori/src/main/resources/application.yml index 091e337..c65ac6f 100644 --- a/dotori/src/main/resources/application.yml +++ b/dotori/src/main/resources/application.yml @@ -6,13 +6,14 @@ spring: password: root jpa: - hibernate: # hibernate ?? ?? + hibernate: ddl-auto: create-drop - properties: # property ?? ?? - hibernate: # hibernate property ?? + properties: + hibernate: + show_sql: true format_sql: true logging: level: org.hibernate.SQL: debug - org.hibernate.type: trace # ?? ???? ????? ???? ?? \ No newline at end of file + org.hibernate.type: trace \ No newline at end of file