스프링 Context가 ContextHolder를 들고 있다. Context안에다가 setAuthentication 셋팅을 해줄 수 있다.
public void login(Account account) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
account.getNickname(), //첫번째 오는 값이 Principal
account.getPassword(),
List.of(new SimpleGrantedAuthority("ROLE_USER")));
SecurityContextHolder.getContext().setAuthentication(token);
}
이 방법은 정석적인 인증방법은 아니다. 하지만 지금은 이게 최선이다. 권한 목록을 받아준다. 그리고 토큰을 설정해주면 로그인이 된다. 토큰을 만들어서 SimpleGrantedAuthority 까지 다 주입을 해서 사용하고 SecurityContextHolder의 getContext에 바로 setAuthentication(token) 을 해준다. 실제 authenticationManager 가 하는 일을 대신 해준다.
인코딩 한 패스워드밖에 접근하지 못하기 때문이다. 정석적인 방법대로 하기 위해서는 plaintext로 받은 (비밀번호) 것을 사용해야 하는데 그 비밀번호는 디비에 저장하지도 않을 것이고 웬만하면 사용하지 않을 것이다. 때문에 정석적인 방법을 사용하지 않고 약간 변형된 방법을 사용했다.
원래 정석적인 방법은 아래와 같다.
public void login(Account account) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContext context = SecurityContextHolder.getContext();
contet.setAuthentication(authentication);
}
테스트를 할때 로그인이 되었는지 안되었는지를 어떻게 확인할 수 있을까? 스프링 시큐리티랑 연동이 되어 있으므로 스프링 부트가 자동 설정으로 인해 mockMvc에다가 여러가지 설정을 해준다. mockMvc에 스프링 시큐리티가 있는 경우에는 스프링 시큐리티를 지원하는 여러가지 기능이 추가된다. 그 예로 csrf ()도 사용할 수 있다.
@DisplayName("인증 메일 확인 - 입력값 오류")
@Test
void checkEmailToken_with_wrong_input() throws Exception {
mockMvc.perform(get("/check-email-token")
.param("token", "sdfjslwfwef")
.param("email", "email@email.com"))
.andExpect(status().isOk())
.andExpect(model().attributeExists("error"))
.andExpect(view().name("account/checked-email"))
.andExpect(unauthenticated()); //인증이 된 사용자이냐 아니냐를 확인할 수 있다.
}
이런 방식으로 아랫줄에 추가해줌!
출처 : 인프런 백기선님의 스프링과 JPA 기반 웹 애플리케이션 개발