인증된 사용자 정보 조회

Spring Security의 Filter들을 모두 거쳐 인증에 통과한 User가 특정 Controller에 도달했을 때, User의 정보가 필요할때가 있다. 이때, Url의 도메인으로 id를 표시하거나 param/body로 계속 전달하기도 무리이며, Filter를 통한 인증시에 이미 한번 유저 정보를 조회하는 로직을 수행하게 된다. 그런데 한번더 select로 조회시 두번 조회하게 되는 비효율적인 상황이 발생하기 때문에 Spring Security의 Context Holder에 들어있는 인증 정보를 가져다 사용하면 Filter에서 인증을 수행한 User의 정보(Details)에 접근할 수 있다.

이 Context Holder에 접근하는 방법은 다음과 같은 방법이 존재한다.


1. @Controller의 메서드에서 매개변수로 입력받기

@Controller
public class UserController{}
  @GetMapping
  public String getMyInfo(Authentication authentication){
    JwtAuthenticationToken authentication = (JwtAuthenticationToken) authentication;
    User user = (User)authentication.getDetails();
    return user.toString();
  }
}

@Controller로 등록된 Bean의 메서드들은 메서드에서 추가 매개변수 인자로 Authentication타입을 받을 수 있다. 위와같이 선언하면 Container가 인증객체를 메서드에 추가해주게 된다.

인증처리과정에서 Custom Authenticaion 객체를 사용하고 있다면 Authentication을 이용해서 명시적 형변환을 이용하거나 처음부터 매개변수타입으로 지정을 할 수 있다.

@Controller
public class UserController{}
  @GetMapping
  public String getMyInfo(JwtAuthenticationToken authentication){
    User user = (User)authentication.getDetails();
    return user.toString();
  }
}

@Controller
public class UserController{}
  @GetMapping
  public String getMyInfo(Principal principal){
    return principal.toString();
  }
}

또한 Authentication 객체 뿐만이 아닌 Principal객체도 주입받아 사용할 수 있다.



2. @AuthenticationPrincipal

@Controller
public class UserController{}
  @GetMapping
  public String getMyInfo(@AuthenticationPrincipal Object principal){
    return principal.toString();
  }
}

//Custom principal
@Controller
public class UserController{}
  @GetMapping
  public String getMyInfo(@AuthenticationPrincipal UserInfo principal){
    return principal.toString();
  }
}

위와같이 어노테이션을 선언 후 통해 현재 사용자의 인증 주체를 주입받을수도 있다. 이때 보통 principal은 Object로 선언되어있기 때문에 Object타입을 주입해주어야하고 Custom한 Principal객체가 있다면 그것을 주입해주어도 가능하다.

다른 타입을 주입시에 null값이 들어가게 된다.



3. SecurityContext

@Controller
public class UserController{}
  @GetMapping
  public String getMyInfo(){
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    //Authentication authentication =  SecurityContextHolder.getContext().getAuthentication();
    UserInfo userInfo = (UserInfo)principal;
    String id = principal.getId();

    return id;
  }
}

가장 원초적인 방법으로는 Container가 주입시켜주는 것이 아닌 SecurityContextHolder에 직접 접근해서 인증 객체를 가져오는 방법으로도 사용자 정보를 가져올 수 있다.

Related Posts

DataType과 변수

DataType과 변수

  • Java
  • 2021년 1월 22일

백기선님의 유튜브 로 진행하시는 스터디를 진행하며 올리는 정리 블로그입니다. 자바에서 데이터 타입은 크게 원시(Primitive) 타입 과 참조(Reference) 타입 이 있다. 1. Primitive Type 정수, 실수, 문자, 논리 리터럴과 같은 실제 데이터 값을 저장하는 타입 종류 데이터 타입 크기(byte) 기본 값 범위 논리형 boolean 1byte false true, false 문자형 char 2byte \u0000 0 ~...

Read More
Tree

Tree

그래프의 일종으로, 여러 노드가 한개의 노드를 가리킬 수 없는 구조 선형구조가 아닌 (비선형), 부모자식의 관계를 가지는 계층형 구조 1. 용어 개념 (설명) Node (노드): 트리를 구성하고 있는 각각의 요소를 의미한다. Edge (= link, 간선) : 트리를 구성하기 위해 노드와 노드를 연결하는 선을 의미한다. Root Node (루트 노드) : 트리 구조에서 최상위에 있는 노드를 의...

Read More
함수

함수

1. 함수 생성 방법 package main func main(){ a := 1 say(a) } func say(a int) { println(a) } func키워드를 이용해서 함수를 선언할 수 있고 가장 기본적으로 만드는 main도 함수 이다. 2. 매개변수(인자) 1) 전달 방식 Java처럼 primitive자료형은 pass by value, reference자료형은 pass by refernece가 아닌 go는 C처럼 *을 이용해서 value인지 refer...

Read More