[Spring Security in action] 권한부여

2024. 1. 20. 10:44·보안

이 블로그는 개인의 공부 목적으로 작성된 블로그입니다. 왜곡된 정보가 포함되어 있을 수 있습니다.

권한 (Authorization)

보안 시스템이 인증, 인가를 제공한다는 것을 들어본적 있을 것이다. 인증이 리소스의 호출자를 판단하는 것이라면 인가는 요청을 승인하는 것으로 권한 부여(Authorization)이 이에 해당한다. 스프링 시큐리터에서는 다음과 같은 순서를 권한부여를 따른ㄴ다.

  1. 클라이언트의 요청
  2. 인증 필터에서 인증을 요청(Authentication Manager에게 위임) or 이미 인증되어이있다면 Security Context에서 인증 정보를 조회
  3. 인증필터가 권한 부여 필터에게 위임
  4. 권한 부여 필터가 권한을 확인
  5. 컨트롤러에게 전달

GrantedAuthority

우리는 이전에 UserDetails 인터페이스를 구현하여 사용자를 정의 할 수 있고, 이때 구현제에 GrantedAuthority 배열을 반환하는 getAuthories 함수가 있었다.

public interface UserDetails extends Serializable {
    String getUserName();
    String getPassword();
    Collection<? extends GrantedAuthority>getAuthorities();
    //중략
    
}

따라서 GrantedAuthority를 확인함으로서 권한(인가)을 구현할 수 있다.

SpringSecurity에서는 GrantedAuthority를 확인하는 몇가지의 메소드를 제공하고 있다.

  • hasAuthority(): 해당 권한이 있는 사용자들만 엔드포인트를 호출할 수 있다.
  • hasAnyAuthority(): 파라미터의 여러 권한중 하나라도 있는 사용자들에게 엔드포인트를 허락한다
  • access(): SpEL 기반의 권한 부여 규칙 메소드 (권장하지 않음)

해당 메서드를 HttpSecurity에 사용하여 권한부여 규칙을 만들 수 있다.

 

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((authz) -> authz
                        .anyRequest().hasAuthority("read")
                )
                .authenticationProvider(customAuthenticationProvider())
                .httpBasic(c -> {
                    c.realmName("OTHER");
                    c.authenticationEntryPoint(new CustomEntryPoint());
                })
                .formLogin(forLogin -> forLogin
                        .successHandler(authenticationSuccessHandler())
                        .failureHandler(authenticationFailureHandler())
                );
        return http.build();
    }

hasAuthority("read") 을 통해 접근권한을 설정 한 것을 확인 할 수 있다. 그러나 우리는 인증에 있어서 AuthenticationSuccessHandler의 구현체에서 equals("read")와 같이 접근 권한을 설정할 수 있었다. 이 방법이 더 좋아 보인다. 엔드포인트에 따라 선택적으로 권한 부여하는 경우에는 고민해봐야 한다.

@Component
public class CustomAuthenticationSuccessHandler implements org.springframework.security.web.authentication.AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        Optional<? extends GrantedAuthority> auth = authorities.stream()
                .filter(a -> a.getAuthority().equals("read"))
                .findFirst();
        if(auth.isPresent()){
            response.sendRedirect("/home");
        }
        else{
            response.sendRedirect("/error");
        }

    }
}

 

이제 우리는 이전에 사용했던 메소드들의 의미를 알 수 있는데, permitAll(), denyAll()이 그예이다.

  • permitAll() 모든 권한에 대해 해당 엔드포인트 접근을 허락하겠음
  • denyAll() 모든 권한에 대해서 해당 엔드포인트 접근을 무조건 거부하겠음

선택기(matcher)를 활용한 권한 부여

위의 방법은 권한과 역활을 기준으로 접근 권한을 부여한다면 특정한 요청 그룹에 대해서 접근 권한을 사용하기 위해서는 선택기를 사용할 수 있다. 경로별로 권한을 분리하는 것이 대표적인 상황이다.

SpringSecurity에서는 3가지의 선택기 메서드의 유형이 존재한다.

  • MVC 선택기 : MVC 식을 활용하여 엔드포인트 선택
  • 엔트 선택기 : 엔트 식을 활용하여 엔드포인트 선택
  • 정규식 선택기 : 정규식을 활용하여 엔드포인트 선택

SpringSecurity 6.0 이상에서는 3가지의 편집기를 deprecated로 지정하고 통일된 requestMatcher를 사용하도록 변경되었음 

https://docs.spring.io/spring-security/reference/5.8/migration/servlet/config.html

 

Configuration Migrations :: Spring Security

In 6.0, @Configuration is removed from @EnableWebSecurity, @EnableMethodSecurity, @EnableGlobalMethodSecurity, and @EnableGlobalAuthentication. To prepare for this, wherever you are using one of these annotations, you may need to add @Configuration. For ex

docs.spring.io

 

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((authz) -> authz
                        .anyRequest().hasAuthority("read")
                        .requestMatchers("/hello1").hasRole("admin")
                        .requestMatchers("/hello2").hasRole("user")
                )
                .authenticationProvider(customAuthenticationProvider())
                .httpBasic(c -> {
                    c.realmName("OTHER");
                    c.authenticationEntryPoint(new CustomEntryPoint());
                })
                .formLogin(forLogin -> forLogin
                        .successHandler(authenticationSuccessHandler())
                        .failureHandler(authenticationFailureHandler())
                );
        return http.build();
    }

requestMatchers("/hello1").hasRole("admin") 와 requestMatchers("/hello2").hasRole("user") 와 같이 엔트포인트를 구별하여 권한을 설정할 수 있음. 이때까지 우리가 사용했던 anyRequest()은 모든 엔트포인트에 대해서 설정하겠다는 의미였다.

또한 경로식으로 엔드포인트를 정의할 수 있다.

ex) requestMatchers("/hello1/**").hasRole("admin") /hello1로 시작하는 모든 경로에 대한 요청 처리

      requestMatchers("/**/hello1").hasRole("admin") /hello1를 포함하는 모든 경로에 대한 요청 처리

정규식도 사용 가능

 

config에 일일히 엔드포인트명시하는 것이 별로 좋지 않은 개발방법 같은데 더 좋은 방법을 생각해볼것

 

'보안' 카테고리의 다른 글

[Spring Security in action] CSRF 보호 및 CORS 적용  (1) 2024.02.03
[Spring Security in action] 인증 필터  (0) 2024.01.20
[Spring Security in action] SecurityContext  (2) 2024.01.18
[Spring Security in action] AuthenticationProvider을 사용한 인증  (0) 2024.01.16
[Spring Security in action] 사용자 관리  (0) 2024.01.15
'보안' 카테고리의 다른 글
  • [Spring Security in action] CSRF 보호 및 CORS 적용
  • [Spring Security in action] 인증 필터
  • [Spring Security in action] SecurityContext
  • [Spring Security in action] AuthenticationProvider을 사용한 인증
bluesparrow
bluesparrow
개인 공부 목적으로 작성된 블로그 입니다.
  • bluesparrow
    Bluesparrow
    bluesparrow
  • 전체
    오늘
    어제
    • 분류 전체보기 (91)
      • 회고 (4)
      • CS (17)
        • 운영체제 (1)
        • 컴퓨터구조 (2)
        • 데이터베이스 (5)
        • 네트워크 (9)
      • PS (7)
        • 백준 (7)
      • 사이드 프로젝트 (12)
      • AI (6)
        • 강화학습 (0)
        • 기계학습 (3)
      • 보안 (13)
      • Java (11)
        • 스프링 부트 (6)
      • 인프라 (4)
        • 도커 (3)
        • AWS (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 회고
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    조합론
    이펙티브 자바
    JPA
    도커
    자바
    컴퓨터구조
    회고
    게임이론
    그래프
    Spring
    이분탐색
    보안
    논문
    BFS
    그리디
    SpringSecurity
    트러블슈팅
    강화학습
    a
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
bluesparrow
[Spring Security in action] 권한부여
상단으로

티스토리툴바