댓글등록 기능까지 이제 마무리하고
예전부터 적용하고 싶었던 구글 로그인 기능을 해보기로 하였다.
먼저 검색하면 정보가 많이 나오는데 OAuth 클라이언트 ID 를 발급받는것부터 시작하면된다.
나는 spring security 의 userdetails를 이미 구현한 상태였으므로
이걸 OAuth 로그인과 어떻게 잘(?) 적용하면 될지 많이 헤맸었다 ..ㅎㅎ
구글로그인과 UserDatils 연동을 위해 중요한 부분만 정리하였다!
CustomOAuth2UserService
@RequiredArgsConstructor
@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
private final MemberRepository memberRepository;
private final HttpSession httpSession;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
// 현재 로그인 진행 중인 서비스를 구분하는 코드
// 이후에 여러가지 추가할 때 네이버인지 구글인지 구분
String registrationId = userRequest.getClientRegistration().getRegistrationId();
// oauth2 로그인 진행 시 키가 되는 필드값 (=Primary Key)
String userNameAttributeName = userRequest.getClientRegistration()
.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2User.getAttributes());
Member member = saveOrUpdate(attributes);
System.out.println(member.getNickname());
System.out.println(member.getPassword());
return new OAuthUser(member, attributes.getAttributes());
}
private Member saveOrUpdate(OAuthAttributes attributes) {
Member member = memberRepository.findByEmail(attributes.getEmail())
.map(entity -> entity.update(attributes.getName(),attributes.getPicture()))
.orElse(attributes.toEntity());
member.setPassword("password");
return memberRepository.save(member);
}
}
먼저 CustomOAuth2UserService를 작성한다. 여기서는 일반 OAuth 예제소스와 별로 다른건 없는데
return해주는 OAuthUser 객체가 핵심이다..
OAuthUser
@Getter
public class OAuthUser implements OAuth2User, UserDetails {
private Collection<? extends GrantedAuthority> authorities;
private Map<String, Object> attributes;
private Member member;
public OAuthUser(Member member) {
List<GrantedAuthority> authorities = Collections.
singletonList(new SimpleGrantedAuthority("ROLE_USER"));
this.member = member;
this.authorities = authorities;
}
public OAuthUser(Member member, Map<String, Object> attributes) {
this.attributes = attributes;
List<GrantedAuthority> authorities = Collections.
singletonList(new SimpleGrantedAuthority("ROLE_USER"));
this.member = member;
this.authorities = authorities;
}
@Override
public Map<String, Object> getAttributes() {
if (this.attributes == null) {
this.attributes = new HashMap<>();
this.attributes.put("name", this.getName());
}
return attributes;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getName() {
return member.getNickname();
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return member.getNickname();
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
UserDatails객체와 연동해주기위해 DefaultOAuth2User 가 아닌 별도로 OAuthUser 클래스를 만들어줬다.
OAuth2User와 UserDetails를 implement 해줘야 한다.
spring security - loadUserByUsername
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<Member> member = memberRepository.findByEmail(email);
Member mem = member.get();
if (mem == null) {
throw new UsernameNotFoundException(email);
}
return new OAuthUser(mem);
}
로그인 인증을 위해 구현했었던 loadUserByUsername 부분이다.
원래는 UserDetail만 구현한 객체를 리턴해줬었는데 새로 생성한 OAuthUser를 리턴해주도록 변경하였다.
OAuth2User, UserDetails 를 함께 구현하는것이 중요하였다.!!
'Study > web' 카테고리의 다른 글
[Spring/JPA] Rest 방식의 댓글 CURD 기능 구현 (0) | 2021.08.17 |
---|---|
[Thymeleaf] Thymeleaf 에서 javascript 사용하기 (0) | 2021.08.08 |
[Thymeleaf] Fragment Layout (0) | 2021.08.08 |
[Thymeleaf] Thymeleaf 와 SpringSecurity (0) | 2021.08.08 |
[JAVA] ByteArray를 이용하여 파일 출력 (0) | 2021.08.07 |