본문 바로가기
Spring&Spring Boot

(Spring) Spring Security란? 개념 및 구조

by Developer RyanKim 2020. 6. 16.

Spring Security

 

https://spring.io/projects/spring-security

 

Spring Security

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

spring.io

Spring.io에서 설명한 Spring Security

: Spring 기반 어플리케이션에서 유연하게 커스터마이징 가능한 접근제어와 인증기능을 제공하는 프레임워크이다.

알아둘 용어 3가지

1. Authentication( :인증)

: 인증을 요청한 주체(user, subject, principal)가 실제 주체인지 여부를 판단

Filter -> Provider 전달되며 인증에 사용되는 핵심객체
인증에 필요한 데이터를 추상화 (ID/Password 방식, JWT 등)

2. Authorization( : 권한)
특정 자원을 사용할 수 있는지 여부를 판단

3. Credential(: 자격증명) : 인증을 위해 전달받는 데이터 (ID/Password 방식에서 password)

Spring Security의 인증 구조

 

  1. Http request (인증요청)
  2. AuthenticationFilter를 거친다(여기서는UsernamePasswordAuthenticationFilter).
    HttpServletRequest를 인터셉트하여 AuthenticationManager에 Authentication 객체를 만들어 (UsernamePasswordAuthenticationToken) 전달한다.
  3. AuthenticationFilter로부터 인증객체 전달 받음.
  4. 해당 인증 객체를 통해 인증을 진행하는 AuthenticationProvider를 찾아 인증 객체(UsernamePasswordAuthenticationToken)를 전달하고 인증을 요청한다.
  5. 6. 7 Provider에서 Service를 호출하여 UserDetails를 통해 인증을 진행한다( DB 데이터 조회 및 검증 )

    8. 9. 10. 인증 성공시 사용자 데이터가 담긴 Authentication 객체를 SecurityContextHolder에 저장하고 AuthenticationSuccessHandle를 실행. (실패시 AuthenticationFailureHandler 실행)

* 인증 성공 후에는 SecurityContextHolder에 Authentication객체가 저장이 되어있고,
재 요청시 쿠키 - 세션을 통해 바로 인증이 가능하다 (인증 프로세스 전체를 하지 않음)

코드 예시

@Component
public class CustomFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        // 인증이 필요한 경우 setAuthentication
        if(isNeedAuth(request)) {
            CustomAuth customAuth = new CustomAuth("");
            SecurityContextHolder.getContext().setAuthentication(customAuth);
        }

        filterChain.doFilter(request, response);
    }

    private boolean isNeedAuth(HttpServletRequest request) {
        return true;
    }
}

@Component
public class CustomProvider implements AuthenticationProvider {

    @Value("${sign}")
    private String sign;
    
    @Override
    public Authentication authenticate(Authentication authentication) {
        // 세션에 Auth 정보를 저장함. 이미 인증받은 상태면 인증 프로세스를 건너뛴다.
        if(authentication.isAuthenticated()) {
            return authentication;
        }

        if(sign.equals(authentication.getPrincipal())) {
            authentication.setAuthenticated(true);
            return authentication;
        } else
            throw new CustomAuthException("");

    }

    @Override
    public boolean supports(Class<?> authentication) {
        return CustomAuth.class.isAssignableFrom(authentication);
    }
}

public class CustomAuth extends AbstractAuthenticationToken {

    private final String principal;

    public CustomAuth(String principal) {
        super(null);
        this.principal = principal;
    }

    @Override
    public Object getCredentials() { return null; }

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

public class CustomAuthException extends AuthenticationException {

    public CustomAuthException(String msg) {
        super(msg);
    }
}

Filter와 Provider를 구현함으로써 커스터마이징한 인증 프로세스를 추가 할 수 있다.

Filter
: Spring Security에서 제공하는 Filter 객체를 상속하여 구현한다.
인증이 필요한지 여부를 판단하고 인증이 필요하면 SecurityContextHolder에 Authentication 객체를 set한다.

Provider: Spring Security에서 제공하는 Provider 객체를 상속하여 구현한다.
supports 메소드를 구현하여 등록된 Authentication 객체에 따라서 동작여부가 결정된다.
Filter - Provider는 서로 관계가 보이지 않고 Authentication 객체로 연결되어있다.
인증 실패시 AuthenticationException을 throw 하도록 되어있다.

 

댓글