본문 바로가기
프로그래밍/스프링 자바

[스프링 시큐리티] 스프링 시큐리티 + Jwt 흐름 알기

by 커피는아아 2021. 7. 12.
반응형

Spring Security

인증(Authentication)과 권한(Authorization)

  • 인증: Id,Pw를 입력 받아 로그인 하는 과정 자체
  • 권한: 보호된 리소스에 접근 가능한지를 결정하는 것을 의미
    • 인가(Authorize): 권한을 부여하는 작업을 인가

Spring Security 구조

다운로드

  • UserDetailsService
    • 실제 DB에서 사용자 인증정보를 가져오는 역할을 한다.
  • UserDetails
    • UserDeatils객체를 통해 권한 정보를 관리하기 때문에 UserDetails를 구현한 구현체가 반드시 필요하다
      • CustomUserDetails를 만들고 Mebmer에 리턴해주는 방식을 채택하였다.
    • 넘겨받은 정보를 통해 DB에서 찾은 사용자 정보
    • UserDetails는 인증용객체(Member)와 도메인용 객체(CustomUserDetails)를 분리하지 않고 인증용 객체에서 상속해서 사용하기도 한다.
      • GrantedAuthority
  • 동작 플로우
    1. Http Request : 사용자가 로그인 정보와 함께 인증을 요청한다.
    2. AuthenticationFilter가 요청을 가로 챈다. 가로친 정보를 바탕으로 UsernamePasswordAuthenticationToken 객체를 생성한다.
    3. AuthenticationFilter가 AuthenticationManger구현체ProviderManager에게 토큰 (UsernamePasswordAuthenticationToken)을 전달한다.
    4. 다시 AuthenticationProvider에 UsernamePasswordAuthenticationToken 객체를 전달합니다.
    5. AuthenticationProvider가 실제 데이터베이스에서 사용자 인증정보를 가져오는 UserDetailsService에 사용자 정보(아이디)를 넘겨줍니다.
    6. 넘겨받은 사용자 정보를 통해 DB에서 찾은 사용자 정보인 UserDetails 객체를 만듭니다.
    7. AuthenticationProvider(인증 제공자) 는 UserDetails를 넘겨받고 사용자 정보를 비교합니다.
    8. 인증이 완료되면 권한 등의 사용자 정보를 담은 Authentication 객체를 반환합니다. (인증 제공자 -> 인증 관리자)
    9. AuthenticationFilter에 Authentication 객체가 반환됩니다.
    10. Authentication 객체를 SecurityContext에 저장합니다.

Spring Security Filter (chaning 방식)

  • 스프링 시큐리티는 필터체인을 통해 다양하게 커스트마이징이 가능하다

  • 필터를 통해 인증과 인가를 하기 때문에 중요하다.

  • UsernamePasswordAuthenticationFilter를 주로 사용

    • login 요청을 감시, 인증 과정을 진행
    • spring security configure를 보면 기존의 필터전에 커스텀한 Jwt필터가 동작하고 UsernamePasswordAuthenticationFilter로 전달하는 역할을 한다.
    .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);

JWT

  • Json 객체를 통해 안전하게 정보를 전송할 수 있는 토큰이다.
    • JWT는 '.' 구분자로 Header(토큰타입,알고리즘방식).payload(실제전달정보).signature(위변조방지값)

구현 (관련 된 곳 숫자를 작성해봄)

https://github.com/seongbinko/simple-order-app config 디렉토리에서 상세 내용은 확인 가능하다.

  • WebSecurityConfig extends WebSecurityConfigurerAdapter

    • @EnableWebSecurity
  • JwtTokenProvider.class

    토큰 생성[10]: 
    
    public String createToken(String nickname, String role) {
            Claims claims = Jwts.claims().setSubject(nickname);
            claims.put("role", role);
            Date now = new Date();
            return Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setClaims(claims) // 데이터
                    .setIssuedAt(now) // 토큰 발행일자
                    .setExpiration(new Date(now.getTime() + tokenValidTime)) // set Expire Time
                    .signWith(SignatureAlgorithm.HS256, secretKey) // 암호화 알고리즘, secret값 세팅
                    .compact(); // String type으로 return
        }
    토큰 인증 정보 조회[6]
          public Authentication getAuthentication(String token) {
            UserDetails userDetails = userDetailsService.loadUserByUsername(this.getUserPk(token));
            return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
        }
  • JwtAuthenticationFilter.class

    [8][9][10]의 과정으로 [11] SecurityContextHolder에 Authentication 객체를 저장한다. 
    • Filter 기능을 사용하여 시큐리티를 동작시키는데 GenericFilterBean은 Filter기능을 사용하면서 Spring config설정 정보를 쉽게 처리하기 위한 GenericFilterBean을 제공한다.
    • GenericBean을 통해 스프링 컨테이너에 올라간 bean(jwtTokenProvider)를 사용할 수 있다.
    • Filter는 servlet기 때문에 servlet의 ServletContext에 spring의 ApplicationContext를 연동해야 한다

참조