@Service
@RequiredArgsConstructor // 의존 객체 주입
@Slf4j
public class MemberService {
// 의존 객체
private final MemberMapper memberMapper;
private final PasswordEncoder encoder;
// 회원 가입 중간 처리
public boolean join(SignUpDto dto) {
// dto -> 엔터티로 변환
Member member = dto.toEntity();
// 비밀번호를 인코딩 (암호화)
String encodedPassword = encoder.encode(dto.getPassword());
member.setPassword(encodedPassword);
return memberMapper.save(member);
}
}
@Getter @Setter @ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode
public class SignUpDto {
@NotBlank(message = "아이디는 필수값입니다.")
@Size(min = 4, max =14, message = "아이디는 4~14글자")
@Pattern(regexp = "^[a-zA-Z0-9]+$", message = "아이디는 영문과 숫자만 포함해야 합니다.")
private String account;
@NotBlank
private String password;
@NotBlank
@Size(min = 2, max = 6) private String name;
@NotBlank
private String email;
// dto -> 엔터티로 변환
public Member toEntity() {
return Member.builder()
.account(this.account)
.password(this.password)
.email(this.email)
.name(this.name)
.build();
}
}
package com.study.springstudy.springmvc.chap05.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@EnableWebSecurity // 시큐리티 설정 파일
public class SecurityConfig {
// 시큐리티 기본 설정 (인증 인가 처리, 초기 로그인화면 없애기)
// @Bean : @Component와 같지만 (@Controller, @Service, @Repository, @Mapper)
// @Bean: 내가 만들지 않은 것 (스프링에서 제공) 스프링에서 주입
// @Component: 내가 만든 것 스프링에서 주입
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // csrf 토큰공격방지 기능 off
// 모든 요청에 대해 인증하지 않겠다.
.authorizeRequests().antMatchers("/**").permitAll();
return http.build();
}
// 비밀번호를 인코딩하는 객체를 스프링 컨테이너에 등록
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
-> kkk1234!라는 비번이 인코딩 되어야 함.
-> DB에서 인코딩이 잘된 것 확인
// 로그인 검증 처리
public LoginResult authenticate(LoginDto dto) {
// 회원가입 여부 확인
String account = dto.getAccount();
Member foundMember = memberMapper.findOne(account);
// 회원가입이 안되었을 때
if (foundMember == null) {
log.info("{} = 회원가입이 필요합니다.", account);
return NO_ACC;
}
// 비밀번호 일치 검사
String inputPassword = dto.getPassword(); // 클라이언트에 입력한 비밀번호
String originPassword = foundMember.getPassword(); // DB에 저장된 비밀번호
// PasswordEncoder에서는 암호화된 비번을 내부적으로 비교해주는 기능을 제공
// 확인해주는 기능만 제공
if (!encoder.matches(inputPassword, originPassword)) {
log.info("비밀번호가 일치하지 않습니다.");
return NO_PW;
}
log.info("{}님 로그인 성공", foundMember.getName());
return SUCCESS;
}
import lombok.*;
@Getter @ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LoginDto {
private String account;
private String password;
private boolean autoLogin; // 자동로그인 체크 여부
}
public enum LoginResult {
SUCCESS, NO_ACC, NO_PW
}
@Controller
@RequestMapping("/members")
@Slf4j
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
//회원가입 양식 열기
// /members로 똑같으면 String -> void, return 생략해도 사이트 연결됨
@GetMapping("/sign-up")
// @ResponseBody // 이거 붙이면 jsp가 아니라 그냥 txt가 날라감
public void signUp() {
log.info("/members/sign-up GET : forwarding to sign-up.jsp");
// return "members/sign-up";
}
// 회원가입 요청 처리
@PostMapping("/sign-up")
public String signUp(@Validated SignUpDto dto) {
log.info("/members/sign-up POST");
log.debug("parameter: {}", dto);
boolean flag = memberService.join(dto);
return flag ? "redirect:/board/list" : "redirect:/members/sign-up"; // 회원가입 성공시 board리스트로
}
}