-
Notifications
You must be signed in to change notification settings - Fork 1
Security Authentication
기존 Security 없이 로그인과정을 구현했지만 Security의 필요성을 느껴 구현하던 도중 Authentication 과정에서 문제가 발생하였다.
Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException
원래대로라면,
회원로그인 → AuthService → UserDetailsService → JwtFilter Authorization → AccessToken, RefreshToken 응답
과정을 거쳐 Authentication/Authorization 과정이 이루어지는데 UserDetailsService에서 무슨 이유인지 NumberFormatException이 발생하였다.
로그를 확인해보니, User Class에서 Name을 String에서 Long Type으로 변경할 수 없다고 나와있었다.
문제가 User Class에서 일어났으니, 해당 부분을 중단점을 찍어 디버깅해보았다.
Authentication 이 진행될 때, User Class에 들어가는 username 부분 값을 확인해보니, memberId가 아니라 email이 들어갔었다..
처음에는, memberId로 Authentication을 구현하려하였지만, 인증 후 인증이 필요한 API 호출에서 로그인한 회원의 정보를 쓰는 경우가 많으므로 CustomUserDetails Class로 만들어 사용해야할 필요성을 느꼈다..!
다른 클래스에서도 인증된 사용자에 대한 email, memberId, role, social 정보가 필요하기 때문에, CustomUser를 만들어 사용하였다. 아래는 해당 CustomUser 클래스이다..
🛠️ User를 상속받는 MemberDetails
- 🟢 서버에서 authorization을 진행할 때 authentication이 필요한 API 요청들은 로그인중인 회원의 정보가 필요하므로, 로그인한 회원의 정보를 전부 사용할 수 있도록 구현하였다.
package com.devcv.auth.details;
import com.devcv.member.domain.Member;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@Getter
public class MemberDetails extends User {
private final Member member;
public MemberDetails(Member member, List<? extends GrantedAuthority> authorities) {
super(member.getEmail(), member.getPassword(), authorities);
this.member = member;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return Collections.singleton(new SimpleGrantedAuthority("ROLE_"+(member.getMemberRole().name())));
}
@Override
public String getPassword() {
return member.getPassword();
}
@Override
public String getUsername() {
return String.valueOf(member.getMemberId());
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MemberDetails that = (MemberDetails) o;
return Objects.equals(member, that.member);
}
@Override
public int hashCode() {
return Objects.hash(member);
}
}