ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • @AuthenticationPrincipal
    Java 2021. 3. 1. 19:00

    Principal

    로그인한 사용자의 정보를 파라미터로 받고 싶을때 Principal 아래와 같이 객체로 받아서 사용할 수 있다.

    Principal 객체는 java.security 패키지에 속해있는 인터페이스이며
    getName() 을 통하여 name 정보를 참조할 수 있다.

    @GetMapping()
    public String index (Model model, Principal principal) {
        if (principal == null) {
            model.addAtrribute("msg", "Hello");
        } else {
            model.addAtrribute("msg", "Hello" + principal.getName());
        }
    
        return "index";
    }

     


    @AuthenticationPrincipal

    다른 방법을 찾아보니 @AuthenticationPrincipal 이 존재한다.
    이 애노테이션은 파라미터와 애노테이션 타입에 적용가능하며 런타임시 작동한다.
    안에 설명을 보면 Authentication.getPrincipal() 메소드 인자로 사용한다고 적혀있다.

    @Target({ ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
    @Retention(RetentionPolicy.RUNTIME)

    파라미터와 애노테이션 타입에 적용가능하며 런타임시 작동한다.

    @GetMapping()
    public String index (@AuthenticationPrincipal User user) {
        if (principal == null) {
            model.addAtrribute("msg", "Hello");
        } else {
            model.addAtrribute("msg", "Hello" + user.getUsername());
        }
    
        return "index";
    }
    Then the user can specify an annotation that looks like:
    @AuthenticationPrincipal(expression = "customUser")

    애노테이션 사용시 UserDetailsService 에서 Return 한 객체를 파라미터로 직접 받아올 수 있다.

     


    현재 Account 에 대한 애노테이션 만들기

    다른 사람이 이렇게 사용한걸 보고 뭔지 모르겠어서 찾아보았다.

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account")
    public @interface CurrentAccount {
    }
    @Getter
    public class UserAccount extends User {
    
        private Account account;
    
        public UserAccount(Account account) {
            super(account.getNickname(), account.getPassword(), List.of(new SimpleGrantedAuthority("ROLE_LEVEL_1")));
            this.account = account;
        }
    }

     

    • 현재 참조중인 객체가 AnnonymousAuthenticationFilter 에 의해 생성된 Authentication 인 경우 null 반환, 아니면 User 를 상속받은 UserAccount 를 반환한다.
    • Account 객체에서 UserDetails를 구현하여 사용하여도 되지만 직접 리턴하는 방법은 도메인 클래스에 영향을 미치니 추천하지 않고 위와 같이 UserAccount 객체를 따로 만듬.

     

    @GetMapping()
    public String index (@CurrentAccount Account account) {
       if (account == null) {
            model.addAtrribute("msg", "Hello");
        } else {
            model.addAtrribute("msg", "Hello" + account.getUsername());
        }
        return "index";
    }

     

     


    정리

    - 기존에는 java.security 의 Principal 을 사용하여 현재 유저를 가져왔는데 참조할 수 있는 정보는 name 뿐이다.

    - 근데 @AuthenticationPrincipal 사용시 UserDetailsService 에서 리턴한 객체를 사용할 수 있다.

    - 그래서 @AuthenticationPrincipal 을 사용.

    - 근데 매번 파라미터에 @AuthenticationPrincipal 사용하는 것도 문제고 위에서 만든 UserAccount 객체가 Account 객체를 감싸고 있으니 직접 접근하려면 매번 .getAccount() 를 통해야 하다보니 중복된다.

    - 그래서 Account 객체를 직접 사용하기 위해서 SpEL 을 지원하는 것을 이용하여 @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account") Account 객체를 직접 가져올 수 있다.

    - 근데 매번 SpEL 을 적으면 코드도 길고 매번 컨트롤러에 적어야한다.

    - 이를 해결하기 위해 @CurrentAccount 라는 커스텀 애노테이션을 만들었다.

     

    'Java' 카테고리의 다른 글

    ModelMapper  (0) 2021.03.04
    @InitBinder  (0) 2021.02.26
    java validation  (0) 2021.02.26
    13. I/O  (0) 2021.02.24
    12. 애노테이션  (0) 2021.02.06
킹수빈닷컴