반응형
authenticatied는 mockMvc에서 제공하는 기능이다.
@DisplayName("회원 가입 화면이 보이는지 테스트")
.andExpect(unauthenticated());
@DisplayName("회원 가입 처리 - 입력값 오류")
.andExpect(unauthenticated());
@DisplayName("회원 가입 처리 - 입력값 정상")
.andExpect(authenticated().withUsername("@"));
@DisplayName("인증 메일 확인 - 입력값 오류 ")
.andExpect(unauthenticated());
@DisplayName("인증 메일 확인 - 입력값 정상")
.andExpect(authenticated().withUsername("@"));
AccountController
@PostMapping("/sign-up") // 복합객체는 본디 ModelAttribute로 받지만, 생략가능
public String signUpSubmit(@Valid @ModelAttribute SignUpForm signUpForm, Errors errors) {
if (errors.hasErrors()) {
return "account/sign-up";
}
// SignUpForm 도메인에 Valid를 위한 처리 필요
// @InitBinder를 이용해 대체
// signUpFormValidator.validate(signUpForm, errors);
// if (errors.hasErrors()) {
// return "account/sign-up";
// }
// -> 자동으로 SignUpForm 검증을 한다.
//이메일 보내는 작업을 컨트롤러가 모르도록 서비스 쪽으로 이전 -> 서비스에서 private으로 수행
//accountService.processNewAccount(signUpForm);
//로그인 처리를 위한 리팩토링
accountService.login(accountService.processNewAccount(signUpForm));
//서비스에서 processNewAccount메서드가 리턴값이 account로 변경
return "redirect:/";
}
-> 회원가입 완료시 login
@GetMapping("/check-email-token")
public String checkEmailToken(String token, String email, Model model) {
Account account = accountRepository.findByEmail(email);
String view = "account/checked-email";
//같은 링크를 리턴하지만, 담은 정보는 각각 다르다.
//해당 뷰에서 error를 담아서 왔을 경우와 setEmailVerified가 true를 담아서 왔을 때를 구분해서 처리
//리파지토리를 도메인 계층으로 생각해, 레이어계층에서의 리파지토리 참조를 자유롭게 한다.
//반대로, 레이어 계층인, 서비스나 컨트롤러를 도메인 계층에서 참조하는 것은 지양한다.
//1단계에서 이메일의 존재여부를 판단
//2단계에서는 해당하는 이메일의 토큰값 동일 여부를 확인한다.
if(account==null) {
//해당 이메일이 존재하지 않을 때 오류 발생
//정보제공을 줄이기 위해 -> 서버단에서만 wrong.email이라는 것을 명시하고, 리턴은 하지않는다.
model.addAttribute("error", "wrong.email");
return view;
}
//토큰이 같지 않다면-> 하나의 메서드로
if(!account.isValidToken(token)) {
model.addAttribute("error", "wrong.token");
return view;
}
//항상 동시에 수행된다면, 하나의 메서드로 묶는다.
account.completeSignUp();
//회원가입이 완료되으므로, 로그인 처리
accountService.login(account);
model.addAttribute("numberOfUser", accountRepository.count());
model.addAttribute("nickname", account.getNickname());
return view;
}
-> 이메일 인증 완료시 login
AccountService
@Transactional
public Account processNewAccount(SignUpForm signUpForm) {
// 1. 회원정보 저장
// 2. 이메일 토큰 만들기
// 3. 이메일 전송
Account newAccount = saveNewAccount(signUpForm);
// 회원가입 이메일 발송 -> starter-mail 이용 -> mailsender // 일단 가짜 객체에 저장해 콘솔에 출력
// 계정인증을 위한 토큰값 생성 -> 유효 아이디를 이용해 랜덤 생성
newAccount.generateEmailCheckToken();
//emailCehckToken=null
//저장 후 토큰 생성 -> 함수안에서만 트랜잭션이 존재하므로, DB에 싱크오류 ->@Transactional 필요
//상태 종료시 DB에 싱크를 해주기 위함
sendSignUpConfirmEmail(newAccount);
// TODO 회원 가입 처리 valid에 안걸리면 회원가입
return newAccount;
//로그인 처리 위해 -> 회원정보를 리턴하도록 변경 후 컨트롤러에서 받는다.
}
-> 로그인할 회원정보를 리턴하기위해 return newAccount로 변경
public void login(Account account) {
// TODO Auto-generated method stub
//스프링 시큐리티에서 컨텍스트 홀더라는 기능을 이용해 간편하게 로그인
//토큰을 이용해 로그인 -> 토큰은, 닉네임, 패스워드, 권한으로 이루어져 있다.
UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(
account.getNickname(),
account.getPassword(),
List.of(new SimpleGrantedAuthority("ROLE USER")));
//권한 목록을 받아서 ROLE USER로 설정
// SecurityContext context =SecurityContextHolder.getContext();
// context.setAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(token);
//해당 토큰을 인증에 사용 ->정석적으로는 form인증할때 username, password를 이용해 AuthenticationManger를 통해 인증
// //정석적인 코드 -> 실제 비밀번호를 접근해야 하므로 사용하기 어렵다.
// UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
// Authentication authentication = authenticationManager.authenticate(token);
// SecurityContext context = SecurityContextHolder.getContext();
// context.setAuthentication(authentication);
}
-> 로그인할 회원정보를 파라미터로 받고 해당 회원정보를 이용해 로그인
-> 이때 필요한 정보는 닉네임, 인덱싱된 패스워드, 권한이다.
-> 스프링시큐리티에서 제공하는 메서드를 이용해 토큰을 가지고 로그인을 수행한다.
ContextHolder -> context -> Authentication -> token
즉, 컨텍스트를 얻어서 인증에 사용하는데, 한 세션에서 필요한 정보를 담고 있기 때문에 token을 context에 담아서 전달
반응형
'Server Programming > Spring Boot Full-Stack Programming' 카테고리의 다른 글
[스프링 풀스택 클론 코딩] 로그인 여부에 따른 네비게이션 메뉴 구성 (0) | 2022.08.29 |
---|---|
[스프링 풀스택 클론 코딩 - 회원가입] (1-12) 회원 가입 메인 네비게이션 메뉴 (0) | 2022.08.29 |
[스프링 풀스택 클론 코딩 - 회원가입] (1-11) 회원 가입 완료 후 자동 로그인 (0) | 2022.08.27 |
[스프링 풀스택 클론 코딩 - 회원가입] (1-10) 회원 가입 인증 메일 확인 테스트 및 리팩토링 (0) | 2022.08.26 |
[스프링 풀스택 클론 코딩] 회원가입 이메일 인증 정상/오류 시 분기 (0) | 2022.08.26 |