처음에는 401 에러이길래 SecurityFilterChain 에서 엔드포인트를 잘못 열어 놓은 줄 알았다.
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
private final TokenProvider tokenProvider;
private final AuthenticationManagerBuilder authenticationManagerBuilder;
...
public RsData<TokenDto> login(LoginDto loginDto) throws Exception {
Member member = memberRepository.findByUsername(loginDto.getUsername())
.orElseThrow(() -> new AccountNotFoundException("User not Found"));
boolean matches = passwordEncoder.matches(loginDto.getPassword(), member.getPassword());
if (!matches) {
throw new NotMatchPasswordException();
}
//토큰 생성, TODO: 분리
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(
member.getUsername(),
member.getPassword());
Authentication authentication =
authenticationManagerBuilder.getObject().authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
TokenDto tokenDto = tokenProvider.createToken(authentication);
return RsData.successOf(tokenDto);
}
}
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
이 부분부터 실행자체가 되지 않았고, 오류나 예외를 던지지도 않았다.
loginDto에는 유저가 직접 입력한 password,
member에는 인코딩된 password가 저장되어 있었다.
UsernamePasswordAuthenticationToken
에 넘겨주는 사용자 이름과 비밀번호가 실제 DB 등에 저장된 사용자 정보와 정확하게 일치하는지 확인authenticationToken = UsernamePasswordAuthenticationToken [Principal=username123, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]
와 같은 형태로 출력되었었다.
UsernamePasswordAuthenticationToken
이 생성되는 시점의 비밀번호는 평문 형태여야 한다. 만약 비밀번호를 해싱해서 저장하고 있다면,UsernamePasswordAuthenticationToken
에 넘겨주는 비밀번호도 평문 형태여야 한다.
따라서, LoginDto.getPassword()를 인자로 주어 생성하였다.
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(
loginDto.getUsername(),
loginDto.getPassword());