스프링 시큐리티 동적권한 검증

Seung jun Cha·2024년 7월 27일
0
post-thumbnail

1. PermissionService, CustomUserDetailService, CustomPermissionEvaluator

  • 블로그에 대해 사용자가 어떤 권한을 가지는지를 판단하는 서비스를 제공합니다. 주로 사용자의 권한을 확인하는 데 사용됩니다.
  • 블로그의 소유자와 사용자의 정보를 비교하여 사용자의 역할을 결정합니다. 블로그의 소유자와 사용자가 동일하면 ROLE_ADMIN 역할을 부여하고, 그렇지 않으면 ROLE_MEMBER 역할을 부여합니다. 로그인하지 않았으면 GUEST 권한을 부여합니다.

  • UserDetailService에 getUserRoleForBlog 메서드가 추가됩니다. determineUserRole 로 결정된 사용자의 권한을 현재 로그인 중인 사용자에게 설정합니다.

  • CustomPermissionEvaluator는 주어진 권한과 대상 객체를 기반으로 권한 검증을 수행합니다. determineUserRole 로 결정된 사용자의 권한으로 api에 접근할 수 있는가를 알려줍니다.

  • PermissionEvaluator : 이 클래스는 주로 Spring Security의 @PreAuthorize 및 @Secured 어노테이션과 함께 사용되며, 특정 도메인 객체와 권한객체를 기반으로 사용자 권한을 평가합니다. 기본적으로 Authentication이 targetDomainObject에 대해 가지고 있는 권한수준을 의미합니다. 지금 판단해야하는건 현재 로그인 중인 사용자가 블로그에 어떤 권한을 가지고 있는가입니다.

    • Authentication authentication : 현재 인증된 사용자의 정보를 담고 있는 객체입니다.
    • Object targetDomainObject : 검증할 특정 도메인 객체의 ID나, 객체 자체가 될 수 있습니다. (해당 도메인에 접근할 수 있는가)
      일반적으로 Long 타입으로 도메인 객체의 식별자를 받습니다.
      예를 들어, 블로그 게시글의 ID를 받아서 해당 게시글이 현재 사용자에게 접근 가능한지 확인합니다.
    • Object permission : targetDomainObject에게 접근하기 위해 사용자에게 요구되는 권한 수준을 정의한다. @PreAuthorize에서 정한 role이 들어가게된다.
      즉, determineUserRole으로 결정된 사용자의 권한과 @PreAuthorize에서 정한 role이 들어간 permission을 비교해서 true와 false를 반환하는 것이다.

  • @EnableMethodSecurity를 추가한다. 그리고 커스텀한 permissionEvaluator를 빈으로 등록한다.
  • Spring Security는 기본적으로 URL 기반의 보안을 제공하며, 이는 웹 애플리케이션의 엔드포인트에 대한 접근 제어를 설정하는 방식입니다. 그러나 때로는 메소드 수준에서 더 세밀한 접근 제어가 필요할 수 있습니다. @Secured, @PreAuthorize, @PostAuthorize, @RolesAllowed 등과 같은 어노테이션을 사용하여 메소드 단위에서 접근 제어 특정 메소드나 서비스의 접근을 제어하고 싶을 때 사용됩니다.
    @Bean
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
        DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
        handler.setPermissionEvaluator(permissionEvaluator);
        return handler;
    }

2. jwt를 사용한 로그인과 api 작동과정

  1. 사용자가 아이디와 비밀번호 입력

  2. 클라이언트가 전송한 인증 정보는 UsernamePasswordAuthenticationToken 객체로 생성

  3. AuthenticationManager는 ProviderManager에게 인증을 위임

  4. UserDetailsService 인터페이스를 구현한 클래스의 loadUserByUsername 메서드를 사용해서 사용자의 정보를 데이터베이스에서 가져옴. 여기선 아이디만 가져가서 사용자 정보를 가져오고 이걸 UserDetails 객체로 만들어서 반환

  5. UserDetails 객체와 클라이언트가 제공한 아이디, 비밀번호를 비교하여 사용자를 인증, 여기서는 블로그의 아이디와 입력받은 아이디를 비교해서 권한까지 설정

  6. 인증에 성공하면 AuthenticationProvider는 인증된 사용자를 나타내는 Authentication 객체를 생성

  7. 이 정보는 Spring Security의 SecurityContextHolder에 설정

  8. API 요청이 컨트롤러로 전달

  9. @PreAuthorize 어노테이션으로 인해 내부적으로 CustomPermissionEvaluator를 호출하여 권한 검증을 수행

0개의 댓글