springframework/시작하자SpringSecurity

40.FilterInvocationSecurityMetadataSource (2)

Jungsoomin :) 2020. 9. 30. 06:22

Map 기반 방식의 DB 연동방법

필요한 클래스는 UrlResourceMapFactoryBean이다. (FactoryBean 구현)

  • DB에서 얻은 권한/자원 정보를  ResourceMap 빈으로 생성하여 UrlFilterInvocationSecurityMetadataSource 에 전달한다

구현

자원, 권한 정보를 넘겨줄 클래스는 FactoryBean 을 구현한다.

제네릭으로 <LinkedHashMap<RequestMatcher, List<ConfigArribute>> 를 선언한다. 

 

  • DB에서 가져올 권한/ 자원 정보를 가져올 Service를 필드로 선언
  • LinkedHashMap<RequestMatcher, List<ConfigAttribute>> 를 필드로 선언
  • getObject() : Map에 정보가 없다면 init() 실행, 있다면 Map을 리턴
  • init() : Service 에서 DB와 커넥트하여 권한과 자원 정보의 매핑 정보를 Map에 저장
  • isSington()  : 싱글톤 여부
  • getObjectType() : LinkedHashMap
public class UrlResourcesMapFactoryBean implements FactoryBean<LinkedHashMap<RequestMatcher, List<ConfigAttribute>>> {

    private SecurityResourceService securityResourceService;
    private LinkedHashMap<RequestMatcher, List<ConfigAttribute>> resourceMap;

    public void setSecurityResourceService(SecurityResourceService securityResourceService) {
        this.securityResourceService = securityResourceService;
    }

    @Override
    public LinkedHashMap<RequestMatcher, List<ConfigAttribute>> getObject() throws Exception {

        if(resourceMap == null){
            init();
        }

        return resourceMap;
    }

    private void init() {
        resourceMap = securityResourceService.getResourceList();
    }

    @Override
    public Class<?> getObjectType() {
        return LinkedHashMap.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

DB 에서 권한, 자원정보를 넘겨줄 Service

  • Service 필드 선언
  • GetterLinkedHashMap을 넘김
  • 반복을 돌며 키( RequestMatcher ) , 값 ( SecurityConfig ) 을 매핑하여 리턴
  • 권한과 자원은 N:M 관계이므로 중간 테이블로 관계를 1:N 관계로 풀어주어야 함
@Service
public class SecurityResourceService {

    private ResourcesRepository resourcesRepository;

    public SecurityResourceService(ResourcesRepository resourcesRepository) {
        this.resourcesRepository = resourcesRepository;
    }

    public LinkedHashMap<RequestMatcher, List<ConfigAttribute>> getResourceList(){

        LinkedHashMap<RequestMatcher, List<ConfigAttribute>> result = new LinkedHashMap<>();
        List<Resources> resourcesList = resourcesRepository.findAllResources();
        resourcesList.forEach(re ->{
            List<ConfigAttribute> configAttributeList =  new ArrayList<>();
            re.getRoleSet().forEach(role -> {
                configAttributeList.add(new SecurityConfig(role.getRoleName()));
            });
            result.put(new AntPathRequestMatcher(re.getResourceName()),configAttributeList);

        });
        return result;
    }
}

SecurityConfig 클래스

 

  • CustomFactoryBean 을 생성하여 주입받은 Service를 준다.
  • CustomFilterInvocationSecurityMetadataSource 클래스의 생성자로 FactoryBeanMap을 넘긴다.

 

@Bean
    public UrlFilterInvocationSecurityMetadataSource urlFilterInvocationSecurityMetadataSource() throws Exception {
        return new UrlFilterInvocationSecurityMetadataSource(urlResourcesMapFactoryBean().getObject(), securityResourceService);
    }

    private UrlResourcesMapFactoryBean urlResourcesMapFactoryBean() {

        UrlResourcesMapFactoryBean urlResourcesMapFactoryBean = new UrlResourcesMapFactoryBean();
        urlResourcesMapFactoryBean.setSecurityResourceService(securityResourceService);

        return urlResourcesMapFactoryBean;
    }