ysk(0soo)
Lifealong
ysk(0soo)
전체 방문자
오늘
어제
  • 분류 전체보기 (238)
    • Java (50)
      • whiteship-java-study (11)
      • Java (28)
      • time (6)
    • Spring (68)
      • JPA (15)
      • Spring (1)
      • SpringBoot (1)
      • SpringMVC (6)
      • Spring Security (22)
      • Jdbc (1)
      • RestDocs (14)
      • log (6)
    • Kotlin (3)
    • Web (2)
      • nginx (1)
    • Database (14)
      • MySQL (5)
      • PostgreSQL (1)
      • SQL (1)
      • Redis (4)
    • C, C++ (0)
    • Git (1)
    • Docker (2)
    • Cloud (3)
      • AWS (3)
    • 도서, 강의 (0)
      • t5 (0)
    • 기타 (7)
      • 프로그래밍 (1)
    • 끄적끄적 (0)
    • CS (14)
      • 운영체제(OS) (2)
      • 자료구조(Data Structure) (9)
    • 하루한개 (12)
      • 우아한 테크코스-10분테코톡 (12)
    • 스터디 (12)
      • 클린 아키텍처- 로버트마틴 (2)
      • JPA 프로그래밍 스터디 (10)
    • 테스트 (34)
      • JUnit (19)
      • nGrinder (2)
      • JMeter (0)
    • Infra (3)
    • 프로그래머스 백엔드 데브코스 3기 (0)
    • 디자인 패턴 (3)
    • Issue (4)
    • system (1)
      • grafana (0)
      • Prometheus (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • github

공지사항

인기 글

태그

  • querydsl
  • java
  • node exporter basic auth
  • 동일성
  • 동시성 제어
  • UserDetailsService
  • DataJpaTest
  • AuthenticationException
  • nginx basic auth
  • 가상 스레드
  • jpa
  • AccessDecisionManager
  • 동등성
  • StructuredConcorrency
  • AccessDecisionVoter 커스텀
  • tree
  • 인가(Authorization) 처리
  • 정규표현식
  • 트랜잭션
  • mysql
  • nGrinder
  • restdocs custom
  • junit5
  • restdocs enum
  • 구조화된 동시성
  • LocalDateTime
  • scope value
  • VirtualThread Springboot
  • FilterSecurityInterceptor
  • 가상 스레드 예외 핸들링

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ysk(0soo)

Lifealong

Spring/Spring Security

AccessDecisionVoter 커스텀

2022. 12. 19. 16:45

요구사항

  • "/admin" URL 접근에 대한 접근 권한 검사
    • Admin 사용자의 로그인 아이디 끝 숫자가 홀수 인 경우 접근 허용
    • URL이 "/admin" 이 아닌 경우 접근을 승인함
  • 기본 expressionHandler를 사용
  • accessDecisionManager 인터페이스 구현체 중 UnanimousBased를 사용

SecurityConfig 구현 - HttpSecurity, AccessDecisionManager 설정

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    public AccessDecisionManager accessDecisionManager() { 
        List<AccessDecisionVoter<?>> decisionVoters = new ArrayList<>();
        decisionVoters.add(new WebExpressionVoter()); // 먼저 넣은 Voter가 실행된다. ROLE_ADMIN 권한 검사가 먼저 이루어짐
        decisionVoters.add(new OddAdminVoter(new AntPathRequestMatcher("/admin")));
        return new UnanimousBased(decisionVoters);
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        return http
            .authorizeRequests()

            .antMatchers("/me").hasAnyRole("USER", "ADMIN")
            .antMatchers("/admin").access("hasRole('ADMIN') and isFullyAuthenticated()") // 어드민 권한은 가진 사용자이고 리멤버미를 통하여 인증된 사용자가 아닌사용자만
            .anyRequest().permitAll()
            .accessDecisionManager(accessDecisionManager()) // 정의된 빈을 기본 AccessDecisionManager 로 사용하도록 Spring Security를 구성
            .and()

            .formLogin()
            .defaultSuccessUrl("/")
            .permitAll()
            .and()

                        ... 생략 
            .build();
    }

}
  • 커스텀 AccessDecisionManager 구현
    • AccessDecisionManager 구현체로 UnanimousBased 구현체를 사용
    • 순차적으로 AccessDecisionVoter 추가
    • WebExpressionVoter
      • OddAdminVoter — 생성자 인자로 해당 voter가 처리해야 하는 URL 패턴을 넘김
  • HttpSecurity 설정

다음처럼 사용해도 된다

@Bean
public AccessDecisionManager accessDecisionManager() {
  List < AccessDecisionVoter << ? extends Object >> decisionVoters = Arrays.asList(
    new AuthenticatedVoter(),
    new RoleVoter(), 
    new WebExpressionVoter(),
    customAccessDecisionVoter
        ); 
  return new UnanimousBased(decisionVoters);

}

OddAdminVoter 클래스 구현

public class OddAdminVoter implements AccessDecisionVoter<FilterInvocation> {

    static final Pattern PATTERN = Pattern.compile("[0-9]+$");

    private final RequestMatcher requiresAuthorizationRequestMatcher;

    public OddAdminVoter(RequestMatcher requiresAuthorizationRequestMatcher) {
        this.requiresAuthorizationRequestMatcher = requiresAuthorizationRequestMatcher;
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

    @Override
    public int vote(Authentication authentication, FilterInvocation object,
        Collection<ConfigAttribute> attributes) {
        HttpServletRequest request = object.getRequest(); //
        if (!requiresAuthorization(request)) { // 요청 URL이 어드민인가.   1
            return ACCESS_GRANTED;
        }
        User user = (User) authentication.getPrincipal();
        String name = user.getUsername();
        Matcher matcher = PATTERN.matcher(name);
        if (matcher.find()) {
            int number = toInt(matcher.group(), 0);
            if (number % 2 == 1) {
                return ACCESS_GRANTED;  // 2
            }
        }
        return ACCESS_DENIED;   // 3
    }

    private boolean requiresAuthorization(HttpServletRequest request) {
        return requiresAuthorizationRequestMatcher.matches(request);
    }

}
  • vote() 메소드가 핵심이다.
    • 1 요청 URL 검사
    • 2 권한 조건에 맞으면 ACCESS_GRANTED 리턴
    • 3 권한 조건에 맞지 않으면 ACCESS_DENIED 리턴
  • supports() 메소드는 Voter 클래스가 특정 구성을 지원하는지 여부를 반환

참조

  • https://www.baeldung.com/spring-security-custom-voter
  • https://www.javadevjournal.com/spring-security/custom-access-decision-voter/
저작자표시 비영리 (새창열림)

'Spring > Spring Security' 카테고리의 다른 글

HeaderWriterFilter - 응답헤더에 보안 관련 헤더 추가하는 필터  (0) 2022.12.19
ExceptionTranslationFilter - 예외 전환 필터  (0) 2022.12.19
AccessDecisionManager, AccessDecisionVoter - 인가 결정 심의자  (0) 2022.12.19
Security 인가 처리 개념 및 과정 (Authorization), AccessDecisionManager  (0) 2022.12.19
FilterSecurityInterceptor - 인가(Authorization) 처리 필터  (1) 2022.12.19
    'Spring/Spring Security' 카테고리의 다른 글
    • HeaderWriterFilter - 응답헤더에 보안 관련 헤더 추가하는 필터
    • ExceptionTranslationFilter - 예외 전환 필터
    • AccessDecisionManager, AccessDecisionVoter - 인가 결정 심의자
    • Security 인가 처리 개념 및 과정 (Authorization), AccessDecisionManager
    ysk(0soo)
    ysk(0soo)
    백엔드 개발을 좋아합니다. java kotlin spring, infra 에 관심이 많습니다. email : kim206gh@naver.com github : https://github.com/devysk

    티스토리툴바