이번에는 사용자별 권한을 DB에 저장하여 동적으로 관리해보자
해당 예시 사이트를 참고했다.
예시와 다르게 JPA를 이용하지않고 유저정보를 직접 DB에서 조회하여 구현했다.
핵심내용과, 수정한 부분만을 살펴보자.
로그인 필터를 만들어준다 (customFilterSecurityInterceptor)
주석을 잘 살펴보자, MetaDataSource를 수정하면 어떤일이 발생하는지 잘 알아두는것이 좋겠다.
@Bean
public FilterSecurityInterceptor customFilterSecurityInterceptor() throws Exception {
FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
// 새로운 보안 메타데이터 소스를 설정하는데, urlFilterInvocationSecurityMetadataSource()라는 메서드로 하겠다는 뜻입니다.
// 그런데 DB 와 연동해서 권한과 자원에 대한 제어를 하는 클래스는 사용자가 직접 구현한 UrlFilterInvocationSecurityMetadataSoruce 가 처리하도록 되어 있기 때문에
// security config의 .anyRequest().authenticated() 구문을 해석할 수가 없고 또한 security config의 .anyRequest().authenticated() 구문에 대한 참조 자체를 하지도 않습니다.
// 즉 인증 사용자 및 비인증 사용자 모두 DB 에서 관리하는 자원과 권한의 정책에 따라 접근여부를 결정해야 합니다.
filterSecurityInterceptor.setSecurityMetadataSource(urlFilterInvocationSecurityMetadataSource()); // 권한정보 셋팅
/**
* affirmativeBased : 하나라도 승인이 있으면 승인 처리
* ConsensusBased : 승인과 거부의 개수를 따져서 다수결 쪽으로 처리
* UnanimousBased : 하나라도 거부가 있으면 거부 처리
*/
filterSecurityInterceptor.setAccessDecisionManager(affirmativeBased());
filterSecurityInterceptor.setAuthenticationManager(authenticationManagerBean()); // 인증매니저
return filterSecurityInterceptor;
}
SecurityResourceService 클래스 경우 DB로부터 조회해온다.
// DB로부터 권한과 자원정보를 가져온다.
LinkedHashMap<RequestMatcher,List<ConfigAttribute>> result = new LinkedHashMap<>();
List<Resources> resourcesList = userMapper.selectResource(); // Resources 데이터 전부 가져오기
List<RoleResources> roleResources = userMapper.selectRoleResource(); // RoleResources 데이터 전부 가져오기
for (int i = 0; i < resourcesList.size(); i++ ) {
List<ConfigAttribute> configAttributeList = new ArrayList<>();
Long resourceId = resourcesList.get(i).getResourceId();
for (int j = 0; j < roleResources.size(); j++ ) {
if (roleResources.get(j).getResourceId() == resourceId) {
configAttributeList.add(new SecurityConfig(roleResources.get(j).getRoleName()));
}
}
if (configAttributeList.size() > 0) {
result.put(new AntPathRequestMatcher(resourcesList.get(i).getResourceName()), configAttributeList);
}
}
그리고 유저별 권한에 따라 접근금지 페이지는 핸들러를 설정하여 커스텀 페이지를 만들면 되겠다.
Security config()에 추가
.and() .exceptionHandling() .accessDeniedHandler() // 권한 인증 실패시 처리할 핸들러
private AccessDeniedHandler accessDeniedHandler() { CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler(); accessDeniedHandler.setErrorPage("/denied"); return accessDeniedHandler; }
+++
추가로 필터를 이용해 동적으로 권한을 구성하는데 있어서, 전체적인 소스를 참고할수 있는 깃헙 주소다
https://github.com/KMSKang/basicsecurity