2.스프링 시큐리티 [OAuth 로그인 -3]
Authentication 사용하기
스프링 시큐리티는 인증된 정보를 Authentication으로 감싸서 Security Context Holder에 보관해 놓는다.
일반 로그인 유저 세션 정보 얻기
아래와 같이 메서드 파라미터로 Authentication을 받거나, @AuthenticationPrincipal 을 부착한
UserDetails 구현체를 받으면(PrincipalDetails implements UserDetails) 로그인한 유저의 세션 정보를 얻을 수 있다.
참고로 Authentication 객체의 getPrincipal()의 리턴 타입은 Object다.
@Controller
public class IndexController {
@GetMapping("/test/login")
public @ResponseBody
String testLogin(Authentication authentication, @AuthenticationPrincipal PrincipalDetails userDetails) {
System.out.println("/test/login======");
PrincipalDetails principalDetails = (PrincipalDetails) authentication.getPrincipal();
System.out.println("authentication : " + principalDetails.getUser());
System.out.println("userDetails:" + userDetails.getUser());
return "세션 정보 확인하기";
}
}
로그를 보면, 결과가 똑같다.
authentication : User(id=1, username=ssar, password=$2a$10$2qissCjGbv8EBCpbp.bfyusrCakaSgeOLnzDTDuHTTpexp5FUJIxq, [email protected], role=ROLE_USER, provider=null, providerId=null, createDate=2021-12-30 11:11:59.0)
userDetails:User(id=1, username=ssar, password=$2a$10$2qissCjGbv8EBCpbp.bfyusrCakaSgeOLnzDTDuHTTpexp5FUJIxq, [email protected], role=ROLE_USER, provider=null, providerId=null, createDate=2021-12-30 11:11:59.0)
OAuth 로그인 유저의 세션 정보 얻기
OAuth 로그인 유저의 세션 정보를 얻는 방법은 약간 다르다.
OAuth 로그인 유저의 경우 UserDetails 구현체로 다운 캐스팅하면 에러가 난다.
대신, OAuth2User로 다운 캐스팅해야 에러가 발생하지 않고 세션 정보를 얻을 수 있다.
이 역시 로그를 보면 결과가 같다. (보안상 이유로 생략)
@Controller
public class IndexController {
@GetMapping("/test/oauth/login")
public @ResponseBody
String testOauthLogin(Authentication authentication, @AuthenticationPrincipal OAuth2User oauth) {
System.out.println("/test/login======");
OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal(); // Oauth 의 경우엔 OAuth2User 로 다운 캐스팅해야 에러 안난다.
System.out.println("authentication : " + oAuth2User.getAttributes());
System.out.println("oauth : "+oauth.getAttributes());
return "oauth 세션 정보 확인하기";
}
}
Authentication 객체가 가질 수 있는 타입 2가지
인증 정보를 담는 Authentication은 UserDetails 구현체 또는 OAuth2User 구현체를 가질 수 있다.
전자의 경우 일반 로그인 유저의 인증 정보를 담고, 후자의 경우는 OAuth 로그인 유저의 인증정보를 담는다.
하지만 이로 발생할 수 있는 문제가 있다.
로그인 방법마다 인증 정보를 담는 객체의 타입이 다르다면, 컨트롤러의 메서드마다 두 구현체를 파라미터로 받아야 할까?
다음과 같이 로직은 똑같은데, 로그인 방법에 따라 파라미터를 달리 해야한다면 유지보수 상에 엄청난 비용이 따른다.
public doSomething(@AuthenticationPrincipal UserDetials userDetails){}
public doSomething(@AuthenticationPrincipal OAuth2User oauth){}
해결책
UserDetials 와 OAuth2User를 모두 implements 한 클래스를 만들고, 이를 사용하면 된다.
public class PrincipalDetails implements UserDetails, OAuth2User {
private final User user;//합성을 이용
private Map<String,Object>attributes;
//일반 로그인 시 사용되는 생성자
public PrincipalDetails(User user) {
this.user = user;
}
//Oauth 로그인 시 사용되는 생성자.
public PrincipalDetails(User user, Map<String, Object> attributes) {
this.user = user;
this.attributes = attributes;
}
//해당 User 의 권한을 리턴하는 메서드
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collect = new ArrayList<>();
collect.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return user.getRole();
}
});
return collect;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
//비밀 번호 만기 여부
@Override
public boolean isCredentialsNonExpired() {
return true;
}
//계정 활성화 여부.
//휴면 계정 전환할 때 쓰임.
@Override
public boolean isEnabled() {
return true;
}
//아래부터 Oauth 관련 메서드. OAuth2User 오버라이드 메서드임.
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
//Oauth 의 기본키 getter 메서드. 잘 안씀.
@Override
public String getName() {
return null;
}
}
이렇게 하면, 로그인 방식에 따라 메소드를 여러개 만들 필요가 없어진다. 예를 들면 다음과 같다.
@GetMapping("/user")
public @ResponseBody
String user(@AuthenticationPrincipal PrincipalDetails principalDetails) {
return "user";
}
Author And Source
이 문제에 관하여(2.스프링 시큐리티 [OAuth 로그인 -3]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@dasd412/2.스프링-시큐리티-Oauth-로그인-3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)