본문 바로가기
Spring

스프링부트 회원가입 구현하기

by 쌩욱 2021. 8. 9.

출처 : 스프링부트 SNS 프로젝트 - 포토그램 만들기 (최주호)

 

1. SecurityConfig 생성

public class SecurityConfig extends WebSecurityConfigurerAdapter{
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// super 삭제 - 기존 시큐리티가 가지고 있는 기능이 다 비활성화됨.
		http.authorizeRequests()
			.antMatchers("/", "/user/**", "/image/**", "/subscribe/**", "/comment/**").authenticated() //이런 주소로 들어오면 인증이 필요해
			.anyRequest().permitAll() //그게 아닌 모든 요청은 허용할게
			.and()
			.formLogin() //로그인 해야지
			.loginPage("/auth/signin") //로그인 페이지 / 인증이 필요하면 여기로 보내
			.defaultSuccessUrl("/"); //로그인이 정상적으로 되면 여기로 보내
	}
}

 

.antMatchers(~) : 해당 주소로 요청이 들어오면

.authenticated() : 인증이 필요하다!

.anyRequest() : 나머지 요청들은

.permitAll() : 다 허용합니다!

.formLogin() : 인증 로그인 필요

.loginPage(~) : 로그인 페이지로 보내!

.defaultSuccessUrl(~) : 로그인이 정상적으로 되면 디폴트로 이곳으로 보내!

 

- antMatchers url에 해당하는 요청을 처음 보내면 로그인 페이지("/auth/signin")로 redirect 해줍니다.

- 로그인을 하게 되면 / 로 가게 됩니다.


2. CSRF 토큰 해제

 

CSRF 토큰이란??

정상적으로 페이지에 접근한 사용자인지 검사하기 위해 CSRF토큰 사용합니다.

 

1). 시큐리티가 클라이언트에게 페이지를 응답할 때(ex. signup.jsp) CSRF토큰을 심습니다.

2). 그러면 input tag에 임시 난수값이 생기게 됩니다.

3). 클라이언트가 폼에 데이터를 넣고 서버에 전송할 때 서버는 시큐리티가 감싸고 있어서 시큐리티가 먼저 검사를 합니다. (서버 도착 전) 
4). 시큐리티는 자기가 심은 CSRF 토큰과 일치하는지 검사를 시행합니다.

 

해당 프로젝트에서는 CSRF 토큰을 비활성화 하겠습니다.

(Default는 활성)

(추후 javascript로 요청할 때 번거로워서)

security config에 http.csrf().disable();

@Override
protected void configure(HttpSecurity http) throws Exception {
		
		http.csrf().disable(); //csrf토큰 비활성화 (디폴트는 활성)
		...
	}

 

3. SignupDto, User 모델 만들기

<!--회원가입 인풋-->
<form class="login__input" action="/auth/signup" method="post">
	<input type="text" name="username" placeholder="유저네임" required="required" />
	<input type="password" name="password" placeholder="패스워드" required="required" />
	<input type="email" name="email" placeholder="이메일" required="required" />
	<input type="text" name="name" placeholder="이름" required="required" />
	<button>가입</button>
</form>

signup.jsp에 회원 가입 시 입력하는 인풋입니다.

 

이를 post 메소드로 받기 위해 DTO 클래스인 SignupDto를 구현합니다.

DTO란 Data Transfer Object로써 데이터를 담아 통신하기 위한 용도로 사용합니다.

@Data //getter , setter
public class SignupDto {
	//Dto : data transfer object , 통신을 위해 데이터를 담아두는 객체
	private String username;
	private String password;
	private String email;
	private String name;

	public User toEntity() {
		return User.builder()
				.username(username)
				.password(password)
				.email(email)
				.name(name)
				.build();
	}
}

 

 

DTO를 받았으면 이를 데이터베이스에 저장하기 위해 모델 클래스 User를 생성합니다.

@Builder : builder()함수를 사용해 해당 객체로 초기화 할 수 있게 해주는 Lombok API 입니다.

@Data : Getter와 Setter를 자동으로 생성해줍니다.

@Id : 데이터베이스의 기본키 설정

@GeneratedValue : 값을 자동으로 생성

@PrePersist : DB에 INSERT 되기 직전에 실행

//DB에 저장하기 위한 모델
//JPA = Java persistence API (자바로 데이터를 영구적으로 저장(DB)할 수 있는 API를 제공)

@Builder //dto를 엔티티로 바꾸기 위해
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity // db에 테이블을 생성
public class User {
	
	@Id //pk로 만들어줌
	@GeneratedValue(strategy = GenerationType.IDENTITY) //번호증가 전략이 데이터베이스를 따라간다. (ex. mysql : auto increment)
	private int id; //나중에 사용자가 많아지게 되면 Long을 써야함
	
	private String username;
	private String password;
	private String name;
	private String website; //웹사이트
	private String bio; //자기소개
	private String email;
	private String phone;
	private String gender;
	
	private String profileImageUrl; // 사진
	private String role; // 권한
	
	private LocalDateTime createDate;
	
	@PrePersist // db에 insert 되기 직전에 실행
	public void createDate() { 
		this.createDate = LocalDateTime.now(); // 
	}
	
}

 

 

그리고 UserRepository와 AuthService도 구현합니다.

//어노테이션 없어도 JpaRepository를 상속하면 IoC등록이 자동으로 됨
public interface UserRepository extends JpaRepository<User, Integer>{

}

인터페이스를 생성하고 JpaRepository<엔티티, PK 타입>을 상속하면 자동으로 Repository가 됩니다.

 

@RequiredArgsConstructor는 final 키워드가 붙은 필드를 초기화해주는 생성자를 자동으로 만들어줍니다. DI에 사용됩니다. 스프링 컨테이너에서 적절한 타입을 찾아 자동으로 주입해줍니다.

@RequiredArgsConstructor
@Service //1. IoC 2. 트랜잭션 관리
public class AuthService {
	private final UserRepository userRepository;
	
	public User 회원가입(User user) {
		//회원가입 진행
		User userEntity = userRepository.save(user); //데이터베이스에 저장하고 저장한 객체 반환
		return userEntity;
	}
}

 

 

마지막으로 컨트롤러에서 SignupDto를 받아 User 엔티티로 만들어 DB에 저장합니다.

//회원가입 버튼 클릭 -> /auth/signup -> /auth/signin
	@PostMapping("/auth/signup")
	public String signup(SignupDto signupDto) { // key=value (x-www-form-urlencoded) , 객체 안의 변수들에 다 담겨서 전달됨 (변수 이름 같아야함!)
		
		//signupDto -> User로 만들기
		User user = signupDto.toEntity();
	
		User userEntity = authService.회원가입(user);
	
		return "auth/signin"; //회원가입 성공하면 로그인 페이지로
	}