spring/spring security
[Spring Security5] 권한 계층구조(roleHierarchy) 설정
moonsiri
2021. 8. 13. 11:16
728x90
반응형
1. roleHierarchy 설정
인가 관련해서는 AccessDecisionManager를 사용합니다. SecurityContextHolder에 저장되어있는 Authentication이 접근하는 리소스에 적절한 ROLE을 가지고 있는지 확인합니다. 확인하는 방법은 세 가지(AffirmativeBased, ConsensusBased, UnanimousBased)가 있는데 그중 AffrimativeBased(여러 Voter 중 하나라도 허용하면 허용)를 기본전략으로 사용합니다.
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
...
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(getFilterSecurityInterceptor(), FilterSecurityInterceptor.class)
...
}
@Bean(name = "filterSecurityInterceptor")
public FilterSecurityInterceptor getFilterSecurityInterceptor() throws Exception {
FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
interceptor.setAccessDecisionManager(accessDecisionManager()); // AccessDecisionManager에 권한검사 위임
interceptor.setSecurityMetadataSource(getReloadableFilterInvocationSecurityMetadataSource());
return interceptor;
}
@Bean(name = "accessDecisionManager")
public AffirmativeBased accessDecisionManager() {
List<AccessDecisionVoter<?>> decisionVoters = new ArrayList<>();
RoleVoter roleVoter = new RoleHierarchyVoter(roleHierarchy());
roleVoter.setRolePrefix("");
decisionVoters.add(roleVoter); //security filter default
AffirmativeBased affirm = new AffirmativeBased(decisionVoters);
affirm.setAllowIfAllAbstainDecisions(false);
return affirm;
}
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER\nROLE_ADMIN > ROLE_DEV");
return roleHierarchy;
}
}
2. Security Tag에 계층구조 적용
ROLE_ADMIN 권한만 보유하고 있어도 ROLE_USER는 하위 권한이니 "ROLE_USER권한 보유" 문구가 노출되어야 합니다.
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<sec:authorize access="hasAnyRole('ROLE_USER')">ROLE_USER권한 보유</sec:authorize>
아래는 security tag 사용 시 권한 계층 구조 적용을 위한 설정입니다. 개인적으론 방법 1을 추천합니다.
방법 1)
accessDecisionManger의 decisionVoters list 순서 중요! security tag에서 권한을 체크할 때 voter의 순서대로 체크하는데 로직이 첫 번째 꺼에 없으면 두 번째 꺼는 무시하고 바로 리턴해버림
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean(name = "accessDecisionManager")
public AffirmativeBased accessDecisionManager() {
RoleVoter roleVoter = new RoleHierarchyVoter(roleHierarchy());
roleVoter.setRolePrefix("");
DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy());
WebExpressionVoter expressionVoter = new WebExpressionVoter();
expressionVoter.setExpressionHandler(expressionHandler);
List<AccessDecisionVoter<? extends Object>> decisionVoters = Arrays.asList(expressionVoter, roleVoter);
AffirmativeBased affirm = new AffirmativeBased(decisionVoters);
affirm.setAllowIfAllAbstainDecisions(false);
return affirm;
}
...
}
방법 2)
webSecurity에 expressionHandler 설정
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy());
web.expressionHandler(expressionHandler);
...
}
...
}
728x90
반응형