스프링 시큐리티의 로그인 기능에 대해서 공부하다가 다음과 같은 예외를 만났다.
InternalAuthenticationServiceException: A granted authority textual representation is required
직역하자면 내부 인증 서비스 예외가 발생하였고, 승인된 표현이 필요하다? 라는 의미인 것 같다. 구글링 해보니 로그인 서비스의 loadUserByUsername 메서드 내부에서 null 값이 들어와서 발생하는 예외라고 하였다. 발생한 위치는 해결한 방법 뒤에 기록해두겠다.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<SiteUser> _siteUser = this.userRepository.findByusername(username);
if (_siteUser.isEmpty()) {
throw new UsernameNotFoundException("사용자를 찾을수 없습니다.");
}
SiteUser siteUser = _siteUser.get();
List<GrantedAuthority> authorities = new ArrayList<>();
if ("admin".equals(username)) {
authorities.add(new SimpleGrantedAuthority(UserRole.ADMIN.getValue()));
}
else {
System.err.println(UserRole.USER.getValue());
authorities.add(new SimpleGrantedAuthority(UserRole.USER.getValue())));
}
return new User(siteUser.getUsername(), siteUser.getPassword(), authorities);
}
우선 loadUserByUsername의 파라미터인 username을 로그로 찍어 콘솔창을 확인해보니 정상적으로 출력되는 것을 확인했다.
브라우저 상에 "사용자를 찾을 수 없습니다" 가 아닌 다른 문구가 뜬것과 로그를 loadUserByUsername의 return 문 바로 직전에 찍었을 때 콘솔 창에 로그가 기록되지 않은 것을 토대로 유저에게 롤을 부여하는 부분에서 에러가 발생했을 것이라 짐작했다.
따라서 UserRole.ADMIN.getValue()를 로그로 찍어보니 아니나 다를까 null 이 찍혔다. 그리고 UserRole 파일을 확인해보니 enum 파일인 UserRole의 생성자 부분에서 변수명을 다르게 쓴 것을 발견했다. 해당 변수명을 일치시켜주니 잘 작동한다.
A granted authority textual representation is required 예외 메시지를 만난다면 당황하지 말고 loadUserByUsername 메서드에 null이 들어가는 부분이 없는지 체크해보자.
에러 발생 위치 확인
내가 작성한 코드에는 사용자에게 부여할 수 있는 롤은 크게 ADMIN과 USER 두 개로 나눈 상태이고, loadUserByUsername에서는 특정 사용자의 아이디를 입력받아 DB에 해당 유저 정보가 있는지 확인하여 유저가 존재한다면 해당 유저가 갖는 롤을 부여하는 방식이다.
if ("admin".equals(username)) {
authorities.add(new SimpleGrantedAuthority(UserRole.ADMIN.getValue()));
}
여기서 SimpleGrantedAuthrity 생성자에 enum 파일인 UserRole의 ADMIN 의 value가 들어가는데
public final class SimpleGrantedAuthority implements GrantedAuthority {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final String role;
public SimpleGrantedAuthority(String role) {
Assert.hasText(role, "A granted authority textual representation is required");
this.role = role;
}
...생략...
}
SimpleGrantedAuthrity에서 전달받은 role이 null 인지 혹은 비어있는지 여부를 Assert.hasText 메서드로 확인한다.
public static void hasText(@Nullable String text, String message) {
if (!StringUtils.hasText(text)) {
throw new IllegalArgumentException(message);
}
}
public abstract class StringUtils {
//생략
public static boolean hasText(@Nullable String str) {
return (str != null && !str.isEmpty() && containsText(str));
//생략
}
만약 전달받은 문자열(role)이 null 이거나 비어있으면 SimpleGrantedAuthority에서 전달받은
"A granted authority textual representation is required"
에러 메시지를 띄우는 것이다.
'SpringBoot' 카테고리의 다른 글
[SpringBoot] 스프링 부트 Hello, World! 페이지 띄우기 (0) | 2023.06.20 |
---|