처음에는 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());