복붙노트

[SPRING] SQL 쿼리를 사용한 동적 스프링 보안

SPRING

SQL 쿼리를 사용한 동적 스프링 보안

안녕하세요, 저는 봄 보안에서 SQL 쿼리를 사용하여 가로 채기 URL 패턴과 액세스를 동적으로 만들고 싶습니다.

일반적으로 XML에서이 유형의 표기법을 사용하며 이러한 값 (/ add-role 및 ROLE_ADMIN)을 데이터베이스에서 가져 오려고합니다.

<intercept-url pattern="/add-role*" access="ROLE_ADMIN" />

이 작업을 동적으로 수행 할 수 있습니까?

해결법

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

    1.스프링 보안 FAQ에서 언급했듯이, 내가해야할 첫 번째 일은 정말로 이것을해야 하는가하는 것입니다. 보안은 복잡하고 구성을 광범위하게 테스트해야합니다. 구성을 동적으로 변경하도록 허용하면 응용 프로그램이 훨씬 취약해질 수 있습니다. 정말로 이것을하고 싶다면, FAQ는이를 달성하기위한 기본 방법을 설명합니다. 나는 아래 FAQ의 답변을 확장했다.

    스프링 보안 FAQ에서 언급했듯이, 내가해야할 첫 번째 일은 정말로 이것을해야 하는가하는 것입니다. 보안은 복잡하고 구성을 광범위하게 테스트해야합니다. 구성을 동적으로 변경하도록 허용하면 응용 프로그램이 훨씬 취약해질 수 있습니다. 정말로 이것을하고 싶다면, FAQ는이를 달성하기위한 기본 방법을 설명합니다. 나는 아래 FAQ의 답변을 확장했다.

    동적으로 보안 URL 매핑을 얻으려면 자체 FilterInvocationSecurityMetadataSource를 구현할 수 있습니다. 예제 구현은 아래와 같습니다.

    참고 : Spring Security가 가로 챈 모든 요청에 ​​대해 getAttributes가 호출되므로 일종의 캐싱이 필요할 것입니다.

    public class JdbcFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    
        public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
            FilterInvocation fi = (FilterInvocation) object;
    
            String url = fi.getRequestUrl();
            HttpServletRequest request = fi.getHttpRequest();
    
            // Instead of hard coding the roles lookup the roles from the database using the url and/or HttpServletRequest
            // Do not forget to add caching of the lookup   
            String[] roles = new String[] { "ROLE_ADMIN", "ROLE_USER" };
            return SecurityConfig.createList(roles);
        }
    
        public Collection<ConfigAttribute> getAllConfigAttributes() {
            return null;
        }
    
        public boolean supports(Class<?> clazz) {
            return FilterInvocation.class.isAssignableFrom(clazz);
        }
    }
    

    네임 스페이스를 사용하여 와이어 링 할 수 없으므로 FAQ에서 다른 팁을 사용하면 다음과 같은 BeanPostProcessor를 사용할 수 있습니다.

    public class FilterInvocationSecurityMetadataSourcePostProcessor implements BeanPostProcessor, InitializingBean {
        private FilterInvocationSecurityMetadataSource securityMetadataSource;
    
        public Object postProcessAfterInitialization(Object bean, String name) {
            if (bean instanceof FilterSecurityInterceptor) {
                ((FilterSecurityInterceptor)bean).setSecurityMetadataSource(securityMetadataSource);
            }
            return bean;
        }
    
        public Object postProcessBeforeInitialization(Object bean, String name) {
            return bean;
        }
    
        public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
            this.securityMetadataSource = securityMetadataSource;
        }
    
        public void afterPropertiesSet() throws Exception {
            Assert.notNull(securityMetadataSource,"securityMetadataSource cannot be null");
        }
    }
    

    위의 빈이 모두 패키지 샘플에 있다고 가정하면 다음 구성을 추가합니다

    <bean class="sample.FilterInvocationSecurityMetadataSourcePostProcessor">
        <property name="securityMetadataSource">
            <bean class="sample.JdbcFilterInvocationSecurityMetadataSource"/>
        </property>
    </bean>
    

    결국 ClassCastException이 발생하면 SEC-1957을 실행 중일 것입니다.이 보안 업데이트는 Spring Security 3.1.1에서 수정되었습니다. +이를 해결하기 위해 최신 버전으로 업데이트하십시오.

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

    2.캔트는 실제로 데이터베이스에서 값을 가져 오지만, 리소스가 실행되도록 허용되는지 평가하는 DecisionManager라는 사용자 지정 코드를 작성할 수 있습니다. 이 코드를 사용하여 데이터베이스에서 데이터를 읽을 수도 있습니다.

    캔트는 실제로 데이터베이스에서 값을 가져 오지만, 리소스가 실행되도록 허용되는지 평가하는 DecisionManager라는 사용자 지정 코드를 작성할 수 있습니다. 이 코드를 사용하여 데이터베이스에서 데이터를 읽을 수도 있습니다.

    <bean id="MyDecisionManagerBean" class="org.springframework.security.vote.UnanimousBased">
        <property name="decisionVoters">
            <list>
                <!-- <bean class="org.springframework.security.vote.RoleVoter"/>  -->
                <bean class="org.springframework.security.vote.RoleHierarchyVoter" >
                     <constructor-arg>
                      <bean class="org.springframework.security.userdetails.hierarchicalroles.RoleHierarchyImpl" factory-bean="roleHierarchyImplFactory" factory-method="createRoleHierarchyImpl"/>
                    </constructor-arg>  
                </bean>
                <bean class="com.mycompany.RoleDenyVoter"/>
                <bean class="com.mycompany.RoleAllowVoter"/>
            </list>
        </property>
    </bean> 
    

    수업은 다음과 같이됩니다.

    public class RoleDenyVoter implements AccessDecisionVoter {
    
        public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
             //read from the DB and decide if access is granted
    

    프로세스는 여기에 문서화되어 있습니다 :

    http://static.springsource.org/spring-security/site/docs/3.0.x/reference/authz-arch.html#authz-voting-based

  3. from https://stackoverflow.com/questions/8381776/dynamic-spring-security-using-sql-query by cc-by-sa and MIT license