Spring/[P] 도서 대여 프로그램

🩵 Spring Security (1) 회원가입 🩵

alsruds 2023. 11. 27. 03:48
📺스프링 시큐리티 강의📺
https://www.youtube.com/playlist?list=PLJkjrxxiBSFCKD9TRKDYn7IE96K2u3C3U

 

1️⃣ build.gradle 에 의존성 추가

...

dependencies {
	...
    
	// spring security
	implementation 'org.springframework.boot:spring-boot-starter-security'
	testImplementation 'org.springframework.security:spring-security-test'
}

...

 

2️⃣ SecurityConfig 파일 작성

· 회원 가입 요청을 받아들이기 위한 경로 허용 : requestMatchers("/user/signin").permitAll()

· 비밀번호는 해시 함수로 암호화한 후 DB 에 저장 : BCryptPasswordEncoder

@Configuration
@EnableWebSecurity // security 활성화
public class SecurityConfig {

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        // 비밀번호를 그대로 저장하지 않고 해시 함수를 이용하여 암호화 처리
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                // 리소스 접근 권한 설정
                .authorizeHttpRequests((auth) -> auth
                        // 적은 순서대로 적용됨 (상단 -> 하단)

                        // .requestMatchers : 특정 경로에 대한 권한 설정
                            // 루트 경로 & 로그인 경로 -> 모두가 접근 가능해야 함 : permitAll
                            // permitAll : 설정한 경로로의 접근을 인증 절차 없이 모두 허용
                        .requestMatchers("/", "/user/login", "/user/signin").permitAll()

                        // /admin 경로는 ADMIN 역할을 지닌 사람만 접근 가능
                        //.requestMatchers("/admin").hasRole("ADMIN")

                        // ** 는 모든 경로 허용
                        // 설정한 경로로의 접근은 설정한 권한을 가진 사용자만 허용 : hasAnyRole
                        //.requestMatchers("/my/**").hasAnyRole("ADMIN", "USER")

                        // 그 외 나머지 리소스는 인증된(로그인한) 사용자만 접근 가능 : anyRequest
                        .anyRequest().authenticated()
                );

        http
                // 로그인 처리 설정
                .formLogin((auth) -> auth
                        //.loginPage("/login") // 로그인 페이지 - 설정하지 않으면 기본 로그인 페이지 사용
                        .loginProcessingUrl("/book") // 인증(로그인) 성공 시 이동하는 페이지
                        .permitAll()
                );

        http
                // csrf 설정 (스프링 시큐리티 사용 시 기본으로 적용됨)
                .csrf((auth) -> auth.disable());

        return http.build();
    }
}

 

3️⃣ 회원 가입 로직 개발

· MemberController

@RestController
@RequiredArgsConstructor
public class MemberController {
    private final MemberService memberService;

    // 회원 가입
    @PostMapping("/user/signin")
    public void register(@RequestBody SignInDto signInDto) {
        memberService.signIn(signInDto);
    }
}

 

· MemberService

@Service
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    // 회원 가입
    public void signIn(SignInDto signInDto) {

        // DB 에 동일한 이메일을 가진 사람이 있는지 검증
        boolean isMember = memberRepository.existsByEmail(signInDto.getEmail());
        if (isMember) {
            throw new RuntimeException("이미 존재하는 회원입니다");
        }

        // DB 에 회원 저장
        Member member = Member.createMember(signInDto, bCryptPasswordEncoder);
        memberRepository.save(member);
    }
}

 

· MemberRepository

@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {

    // 회원 가입 - 중복 회원 검증
    boolean existsByEmail(String email);
}

 

· SignInDto

@Getter
@NoArgsConstructor
public class SignInDto {
    private String email;
    private String password;
    private String nickname;
    private String phoneNum;
    private MemberGender gender;

    @Builder
    public SignInDto(String email, String password, String nickname, String phoneNum, MemberGender memberGender) {
        this.email = email;
        this.password = password;
        this.nickname = nickname;
        this.phoneNum = phoneNum;
        this.gender = memberGender;
    }
}

 

· Member

☑️ email 칼럼에 unique 설정

☑️ createMember 메소드 추가

...
public class Member extends BaseEntity {

    @Column(nullable = false, length = 50, unique = true)
    private String email;
    
    ...

    public static Member createMember(SignInDto signInDto, BCryptPasswordEncoder bCryptPasswordEncoder) {
        Member member = Member.builder()
                .email(signInDto.getEmail())
                .password(bCryptPasswordEncoder.encode(signInDto.getPassword()))
                .nickname(signInDto.getNickname())
                .phoneNum(signInDto.getPhoneNum())
                .inactiveDate(null)
                .gender(signInDto.getGender())
                .status(MemberStatus.ACTIVE)
                .build();
        return member;
    }
}

 

4️⃣ Postman 으로 API 요청 테스트 (+ DataGrip 으로 테이블 확인)

· Postman

 

· DataGrip

저장 성공 ~.~