로그인 401 에러 UsernamePasswordAuthenticationToken

kkambbak1·2023년 11월 28일
1

처음에는 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가 저장되어 있었다.

  1. 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()); 
profile
윤성

0개의 댓글