복붙노트

[SPRING] 최대 절전 모드 필터 또는 다른 방법을 사용하여 스프링 데이터 JPA에서 행 수준의 보안을 구현하는 방법?

SPRING

최대 절전 모드 필터 또는 다른 방법을 사용하여 스프링 데이터 JPA에서 행 수준의 보안을 구현하는 방법?

정보 소프트웨어에서 매우 중요한 문제 중 하나는 각기 다른 임무와 접근 수준을 가진 다양한 역할을 가진 사용자가 있다는 것입니다. 예를 들어 다음과 같은 구조 (계층 구조)를 가진 조직을 생각해보십시오.

[Organization Role ]     [Organization ID]
 CEO                        org01
   Financial Assistant      org0101
           personnel 1

   Software Assistant       org0102
           personnel 2

   Commercial Assistant     org0103
           personnel 3

이 조직이 인사 정보를 관리하는 시스템을 가지고 있다고 가정 해보십시오. 이 시스템에서 인사 정보를 표시하는 규칙은 각 사용자가 자신이 액세스 할 수있는 조직의 인사 정보를 볼 수 있다는 것입니다. 예를 들어 'user1'은 '재무 보조'및 '상업 보조'수준에 액세스 할 수 있으므로 '직원 1'및 '직원 3'의 정보 만 볼 수 있습니다. 마찬가지로 'user2'는 'Commercial Assistant'레벨에만 액세스 할 수 있으므로 'personnel 3'의 정보 만 볼 수 있습니다. 따라서이 시스템의 각 사용자는 특정 액세스 수준을 갖습니다. 이제이 시스템에서 각 사용자는 그가 로그인 한 후에 액세스 권한이있는 개인 정보 만 볼 수 있습니다.이 시스템의 테이블 구조를 다음과 같이하면됩니다.

[Organization]
id
code
name

[Employee]
id
first_name
last_name
organization_id

[User]
id
user_name
password

[UserOrganization]
user_id
organization_id

아래 쿼리는 각 사용자에 대해 적절한 인사 정보 결과를 얻는 데 충분합니다.

select *

from employee e 

where e.organization_id in

(select uo.organization_id

 from user_organization uo

 where uo.user_id=:authenticatedUserId)

아래에서 알 수 있듯이 올바른 데이터를 표시하기위한 액세스 논리를 정의합니다.

e.organization_id in

(select uo.organization_id

 from user_organization uo

 where uo.user_id=:authenticatedUserId)

이러한 종류의 액세스 수준은 '행 수준 보안'(RLS)이라고도합니다. 반면에, 해당 리포지토리 클래스에는 아마도 데이터를 읽는 책임을지는 몇 가지 메서드가 있으며,이 모두가 적절한 액세스 수준 조건을 충족해야합니다. 이 경우 액세스 수준 조건은 일부 장소 (메소드)에서 반복됩니다. '최대 절전 필터'를 사용하는 것이이 문제에 대한 적절한 해결책이 될 것 같습니다. 필요한 유일한 것은 인증 된 사용자의 ID를 얻고 모든 읽기 메소드 전에 'enablefilter'명령을 실행하는 필터입니다.

@Filters( {
  @Filter(name=“EmployeeAuthorize", condition="(organization_id in (select uo.organization_id from user_organization uo where uo.user_id=:authenticatedUserId) )  ")
} )

이제 문제는 제안 된 솔루션이 맞습니까? 그렇다면 스프링 데이터에서이 방법을 어떻게 활용할 수 있습니까? 추신 : 우리가 데이터베이스에 의존하고 싶지 않다는 것을 감안할 때, 데이터베이스 측에서의 구현은 후보 솔루션이 될 수 없다. 따라서 우리는 애플리케이션 측 (레벨)에서이를 구현해야한다.

해결법

  1. ==============================

    1.Ali, 재미있는 시나리오입니다.

    Ali, 재미있는 시나리오입니다.

    여기서 대답해야 할 두 가지 질문이 있습니다.

    첫 번째 질문 - 데이터를 노출 할 때 시스템에서 필터링을 수행 할 것인가 아니면 그 이상으로 넘어갈 것입니까? 예를 들어 사용자 / {id}와 같은 작업을 노출하는 경우 권한을 확인하고 사용자가 해당 작업에 액세스 할 수 있는지 확인해야합니다. / users와 같은 작업을 단순히 노출하면 현재 사용자가 볼 수있는 권한이있는 사용자 만 노출되므로 필터링 만 있으면됩니다. 그 구별은 많은 구현을 결정할 것입니다.

    두 번째 질문은 다음과 같습니다. - 수작업으로 얼마나 많은 일을 할 수 있습니까?

    한 손으로 프레임 워크에 필요한 데이터를 적용 할 수 있으며 내장 기능 (보안 표현식, ACL)에 가능한 한 많이 의지 할 수 있습니다. 또는 다른 한편으로는 코드를 데이터 구조에 적용 할 수 있습니다. 수동으로 작업하십시오.

    그것들은 먼저 다른 것에 앞서 두 가지 요소에 초점을 맞 춥니 다. 왜냐하면 구현은 4 가지 결정에 따라 완전히 다르게 보일 것이기 때문입니다.

    마지막으로, 당신의 "할 수있는 ACL 척도"질문에 대한 답변 - 두 가지 빠른 메모. 하나 - 테스트해야합니다. 예, ACL은 확장 할 수 있지만 10K 또는 100K로 확장 할 수 있는지 여부는 테스트하지 않고 구체적으로 대답 할 수있는 질문이 아닙니다.

    둘째, 테스트 할 때 현실적인 시나리오를 생각해보십시오. 솔루션의 한계를 이해하는 것이 중요합니다. 그러나 그 이상으로, 시스템에 1M 개의 엔티티가 있다고 생각하면 좋습니다. 그러나 그렇지 않다면 - 목표를 세우지 마십시오.

    희망이 도움이됩니다.

  2. ==============================

    2.Spring을 사용하면 다음과 같은 것들을 사용할 수 있습니다 :

    Spring을 사용하면 다음과 같은 것들을 사용할 수 있습니다 :

    1) @Query 주석의 SpEL 표현식에서 보안 속성 및 표현식을 사용할 수있게 해주는 SpEL EvaluationContext 확장을 사용할 수 있습니다. 이렇게하면 현재 사용자와 관련된 비즈니스 객체 만 가져올 수 있습니다.

    interface SecureBusinessObjectRepository extends Repository<BusinessObject, Long> {
    
        @Query("select o from BusinessObject o where o.owner.emailAddress like ?#{hasRole('ROLE_ADMIN') ? '%' : principal.emailAddress}")
        List<BusinessObject> findBusinessObjectsForCurrentUser();
    }
    

    2) Web Security Express에서 Bean을 참조하고 경로 변수를 사용할 수 있습니다. 이렇게하면 현재 사용자에게 허용 된 개체에만 액세스 권한을 부여 할 수 있습니다.

    @Service
    public class UserService {
        public boolean checkAccess(Authentication authentication, int id) {
            // ...
        }
    }
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        // ...
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                .antMatchers("/businessObjects/{id}/**").access("@userService.checkAccess(authentication, #id)")
                // ...
        }
    }
    

    자세한 내용은 데모 프로젝트를 확인하십시오. 이 예에서 사용자는 해당 사용자와 관련된 카테고리에 속한 경우 Rooms에 액세스 할 수 있습니다. 관리자는 모든 객실에 액세스 할 수 있습니다.

  3. from https://stackoverflow.com/questions/46757398/how-to-implement-row-level-security-in-spring-data-jpa-using-hibernate-filter-or by cc-by-sa and MIT license