Spring Security (4) - Authentication, SecurityContextHolder의 이해

hyozkim·2020년 5월 17일
1

Spring Security

목록 보기
4/6
post-thumbnail

이번 포스팅에서는 스프링 시큐리티의 핵심인 Authentication에 대해서 알아보자.

그리고 Authentication을 보관하는 SecurityContextHolder에 대해 알아보자.

Authentication

Authentication은 인증 정보를 의미하는 인터페이스다.

Authentication 인터페이스에서 제공하는 메소드

  • Object getPrincipal(); // 주로 ID
  • Object getCredentials(); // 주로 비밀번호
  • Object getDetails(); // 사용자 상세정보
  • Collection<? extends GrantedAuthority> getAuthorities(); // 사용자 권한 목록
  • boolean isAuthenticated(); // 인증여부
  • void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; // 인증 전 false 인증 후 true

이제 주요 핵심 메서드에 대해 살펴보아유~~

Object getPrincipal()

_ Principal을 사전 검색해보자. _

(활동의) 주도자, 주역; 주연 배우; 주 연주자.
[법률] (대리인에 대한) 본인; (보증 채무의) 주 채무자; 정범, 주범

여러가지 뜻이 있지만 주된 사용자 본인이 가장 적절하게 생각되는 뜻이라.
여기서 반환되는 부분이 Object인데 어떤 객체라도 들어갈 수 있다는 것이다.
예를 들어 Long idString name, String email 또, JwtAuthentication 객체가 들어갈 수도 있다.

Object getCredentials()

_ Credentials를 사전 검색해보자. _

자격
자격 인증서, 자격증

말 그대로 자격이다. Principal에서는 사용자 본인을 의미한다면 Credentials은 그에 따른 자격을 증명하고자 할 때 사용된다. Principal과 마찬가지로 구현에 따라 어떤 정보가 들어갈지 달라지지만 대체적으로 암호화된 정보를 저장하며, 보안에 신경을 많이 쓰는 정보이다.

주로 인증 단계에서 패스워드가 들어가고, JWT 인증 완료 후에는 null값을 넣었다.

Object getDetails()

이 부분은 현재 인증 중이거나 인증 완료 후 사용자의 부가적인 정보를 저장한다.
난 이번에 로그인 후 생성된 User 객체와 JwtToken을 주로 저장하였다.

따라서, Controller endpoint에서 반환할 때, (Authentication)객체의 getDetails()가 곧 ResponseDto가 된다.

Collection<? extends GrantedAuthority> getAuthorities()

이 메서드는 JWT 토큰에 Role을 담아 보내듯 스프링 시큐리티 내에서 같은 역할을 한다고 생각한다. 우선 로그인 인증이 완료되면 JWT 토큰을 클라이언트에게 전달하게 된다.

스프링 시큐리티 필터에서 사용자의 권한 체크할 때 사용된다.

보통 DB에 저장해두며 JWT 토큰 안에 Role에 대한 정보(USER, MANAGER, etc)가 들어있기 때문에 사용자가 JWT 토큰을 갖고 HTTP URI 접근할 때 ROLE 정보만 가지고 인증이 된다.

GrantedAuthority 클래스는 사용자의 지정한 권한 범위를 기술하기 위해 추상화된 클래스다.

구현체 클래스 종류 JaasGrantedAuthority, SimpleGrantedAuthority, SwitchUserGrantedAuthority


Authentication 커스텀 구현체 클래스 Example

이번 인증을 구현하면서 JWT 토큰 인증 정보를 구현하기 위해 JwtAuthenticationToken 클래스를 작성하였다.

Authentication 인터페이스 구현체 클래스인 AbstractAuthenticationToken를 상속받아 커스텀하였다.

public class JwtAuthenticationToken extends AbstractAuthenticationToken {
    private final Object principal;

    private final String credentials;

    public JwtAuthenticationToken(String principal, String credentials) {
        super(null);
        setAuthenticated(false);
        this.principal = principal;
        this.credentials = credentials;
    }

    public JwtAuthenticationToken(Object principal, String credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        setAuthenticated(true);
        this.principal = principal;
        this.credentials = credentials;
    }

    @Override
    public String getCredentials() {
        return credentials;
    }

    @Override
    public Object getPrincipal() {
        return principal;
    }
}

SecurityContextHolder

모든 접근 주체는 Authentication을 생성한다.

이것은 SecuriyContext에 접근 주체(Authentication)와 인증정보(GrantedAuthority)을 담겨져 사용된다.

현재 로그인한 사용자 정보를 가지고 있는 바스켓(?)이라 생각하면 될 듯 하다.

ThreadLocal에 보관되며, SecurityContextHolder를 통해 접근할 수 있다.

💡 Tips
Spring Security 3.2 부터는 annotation을 이용하여 현재 로그인한 사용자 객체를 인자에 주입할 수 있다.

@AuthenticationPrincipal 어노테이션을 사용하여 SecurityContextHolder.getContext().getAuthentication() 처럼 현재 사용자 정보를 가져와 사용할 수 있다.

로그인 인증 중 SecurityContextHolder에 Authentication set Example

JwtAuthenticationToken authToken = new JwtAuthenticationToken(authRequestDto.getPrincipal(), authRequestDto.getCredentials());
Authentication authentication = authenticationManager.authenticate(authToken); // 로그인 인증
SecurityContextHolder.getContext().setAuthentication(authentication); // 접근 주체를 담음

참고

다음 블로그들을 참고하여 작성하였습니다.
https://brunch.co.kr/@sbcoba/12
https://sjh836.tistory.com/165
(Spring Security) SecurityContextHolder로 사용자 정보 가져오기

(프로그래머스) 단순 CRUD는 그만! 웹 백엔드 시스템 구현 온라인 스터디(Java반) 강의를 수강하고 제가 이해한대로 정리했습니다. 문제가 될시 삭제하겠습니다!

profile
차근차근 develog

2개의 댓글

comment-user-thumbnail
2021년 3월 23일

작성해주신 글 잘 읽었습니다. 감사합니다.

혹시 한가지 질문을 해도 될까요?
제가 Spring Security, JWT, Redis를 이용하여 로그인 기능을 만들려고 합니다.
제가 진행하는 프로젝트에서는 OncePerRequestFilter(이후 Filter)를 통해서 JWT를 확인하고 있습니다. 그래서 로그인한 유저는 JWT를 가지고 요청을 하도록 하여 Filter에서 SecurityContextHolder에 계속해서 Authentication을 Set하고 있는데 그러는게 아니라 로그인 수행 당시에만 Authentication을 Set해야하는 건가요?

댓글 읽어주셔서 감사합니다. 제가 글을 잘 못써서... 하하 죄송합니다.

1개의 답글