개요
- Voter 를 커스텀해서 IP 를 검증하는 로직을 추가할 수 있다.
Voter custom 하기
- 특정한 IP 만 접근이 가능하도록 하고 싶다면, IP 를 심의하는 Voter 추가하면 된다.
- AccessDecisionManager 의 구현체중 AffirmativeBased 가 기본적략이기 때문에 Voter 중 하나만 통과되도 허용된다.
- 또한 나는 직접 만든 IpAddressVoter 에서 허용되지 않으면, 바로 자원접근을 거부하고 싶다.
- 그렇기 때문에 아래와 같은 규칙이 필요하다.
- AffirmativeBased 에서 직접만든 IpAddressVoter 를 우선적으로 체크해야 되기 때문에 가장 상위에 위치시켜서 먼저 검사하도록 설정해야 한다.
- 허용된 IP의 경우 ACCESS_GRANTED 가 아닌 ACCESS_ABSTAIN 를 리턴해서 추가 심의를 계속 진행하도록 한다.
- 허용되지 않은 IP의 경우 ACCESS_DENIED 가 아닌 AccessDeniedException 를 던져서 최종 자원 접근을 거부시키는 것이다. -> 만약 ACCESS_DENIED 이면 다음 Voter 를 검사하기 때문이다.
코드 구현
public class IpAddressVoter implements AccessDecisionVoter<Object> {
private SecurityResourceService securityResourceService;
public IpAddressVoter(SecurityResourceService securityResourceService) {
this.securityResourceService = securityResourceService;
}
@Override
public boolean supports(ConfigAttribute attribute) {
return (attribute.getAttribute() != null);
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@Override
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> configList) {
if (!(authentication.getDetails() instanceof WebAuthenticationDetails)) {
return ACCESS_DENIED;
}
WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails();
String address = details.getRemoteAddress();
List<String> accessIpList = securityResourceService.getAccessIpList();
int result = ACCESS_DENIED;
for (String ipAddress : accessIpList) {
if (address.equals(ipAddress)) {
return ACCESS_GRANTED;
}
}
if(result == ACCESS_DENIED){
throw new AccessDeniedException("Invalid ipAddress can not accessed");
}
return result;
}
}
- AccessDecisionVoter 클래스를 구현하고 있다.
- 위와 같이 vote 메소드에서 위에서 설정한 규칙을 구현한다.
Security Config 파일 설정
private AccessDecisionManager affirmativeBased() {
AffirmativeBased affirmativeBased = new AffirmativeBased(getAccessDecisionVoters());
return affirmativeBased;
}
private List<AccessDecisionVoter<?>> getAccessDecisionVoters() {
List<AccessDecisionVoter<? extends Object>> accessDecisionVoters = new ArrayList<>();
accessDecisionVoters.add(new IpAddressVoter(securityResourceService));
accessDecisionVoters.add(roleVoter());
return accessDecisionVoters;
}
- AccessDecisionManager 의 디폴트 구현체인 AffirmativeBased 는 하나만 통과해도 전부 통과 시키는 전략이다.
- 그렇기 때문에 Voter 중에서 가장먼저 IpAddressVoter 를 검사해야 IP 검사를 정상적으로 처리할 수 있다.
- 그렇기 때문에 accessDecisionVoters 에 가장 첫번째로 IpAddressVoter 를 위치시킨다.
REFERENCES
- 정수원님의 스프링 시큐리티
'Spring Security' 카테고리의 다른 글
URL 시큐리티 프로세스 커스텀 (0) | 2022.02.28 |
---|---|
권한 계층 적용하기 (0) | 2022.02.28 |
@AuthenticationPrincipal (0) | 2022.02.28 |
메소드 시큐리티 (0) | 2022.02.28 |
Custom DSL 적용 (0) | 2022.02.28 |