Skip to content

Commit

Permalink
feat : 로그인, 회원가입 api 시범 구현(Season-Hackathon#3)
Browse files Browse the repository at this point in the history
- User 도메인 클래스 개발
- Security 커스터마이징을 위한 클래스 오버라이딩
  • Loading branch information
seminchoi committed Feb 16, 2023
1 parent 0a69317 commit 7563fe1
Show file tree
Hide file tree
Showing 12 changed files with 315 additions and 4 deletions.
Binary file modified .DS_Store
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package season.blossom.dotori.user;

import lombok.Data;

@Data
public class AuthRequestDto {
private String email;
private String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package season.blossom.dotori.user;

import lombok.Getter;


@Getter
public enum Authority {
ROLE_USER, ROLE_ADMIN
}
Original file line number Diff line number Diff line change
@@ -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<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> 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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);

}

}
40 changes: 40 additions & 0 deletions dotori/src/main/java/season/blossom/dotori/user/User.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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<HttpStatus> 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);
}



}
Original file line number Diff line number Diff line change
@@ -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<User,Long> {
Optional<User> findByEmail(String email);
}
9 changes: 5 additions & 4 deletions dotori/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 # ?? ???? ????? ???? ??
org.hibernate.type: trace

0 comments on commit 7563fe1

Please sign in to comment.