Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20241118 Spring Security에서 권한별 URL 접근 제어에 대한 고민 본문

개발Article

[TIL]20241118 Spring Security에서 권한별 URL 접근 제어에 대한 고민

최밤빵 2024. 11. 19. 00:56

Spring Security를 사용하면서, 한 유저에게 부여된 권한에 따라 접근 가능한 URL을 나누고자 한다. 예를 들어, guest, user, admin과 같은 권한을 나눠서, user 권한이 있는 사람만 접근할 수 있는 URL에 guest 이용자가 접근하지 못하게 제한하고 싶다. 이 문제를 해결하기 위한 방법으로 몰랐던 방식을 알게됐고, 그 방법에 대한 의견을 정리하면서 이 개발일지를 작성하게되었다. 

  1. SecurityConfig에서 경로별 접근 제한 설정
  2. @PreAuthorize 어노테이션을 사용한 메서드 단위 접근 제한

▶첫 번째 방법: SecurityConfig 파일에서 경로 제한 설정

첫 번째 방법은 SecurityConfig 파일에서 URL 경로별로 접근 권한을 설정하는 것이다. 스프링 시큐리티에서 제공하는 .requestMatchers() 메서드를 이용해 특정 경로에 접근할 수 있는 권한을 제한할 수 있다. 예를 들어, 아래와 같이 /user/** 경로에 대해 USER 권한이 있는 사람만 접근 가능하도록 설정할 수 있다.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .requestMatchers("/user/**").hasRole("USER")
        .requestMatchers("/admin/**").hasRole("ADMIN")
        .anyRequest().permitAll();
}

→ 이 방법은 경로별로 명확하게 접근 권한을 설정할 수 있어, 각 경로에 대한 권한 정책이 한눈에 보인다는 장점이 있다. 따라서 보안 관련된 설정이 한 곳에 모여 있어 관리가 용이하고, 코드의 흐름을 쉽게 파악할 수 있다.


▶두 번째 방법: @PreAuthorize 어노테이션을 사용한 접근 제한

두 번째 방법은 스프링의 @PreAuthorize 어노테이션을 사용하는 것이다. 이 어노테이션은 메서드 단위로 접근 권한을 제어할 수 있게 해준다. 예를 들어, 특정 메서드에 대해 USER 권한이 있는 경우에만 접근하도록 설정하려면 다음과 같이 작성할 수 있다.

@PreAuthorize("hasRole('USER')")
public String userPage() {
    // 사용자 페이지 로직
}

→ 이 방법은 세밀한 접근 제어가 필요할 때 유용하다. 보안이 중요한 특정 메서드에 대해 권한을 설정할 수 있으며, 메서드 레벨에서 바로 권한을 확인할 수 있기 때문에 코드의 비즈니스 로직과 보안 로직을 결합하여 좀 더 명시적으로 표현할 수 있다.


나는 현재 첫 번째 방법을 사용하고 있지만, 두 번째 방법인 @PreAuthorize 어노테이션을 사용한 접근 제한에 대해서도 관심이 생겼다. 이 방법을 학습하면서 몇 가지 장단점과 고려 사항을 알게 되었다.

  • 장점:
    • @PreAuthorize는 메서드 단위로 접근 권한을 설정할 수 있기 때문에 세밀한 권한 제어가 가능하다. 예를 들어, 특정 메서드에 대해 사용자 권한을 제한하고자 할 때, 메서드에 직접적으로 권한을 명시함으로써 보안 로직을 명확하게 표현할 수 있다.
    • 코드가 더 직관적이고, 메서드 자체에서 권한을 확인하기 때문에 해당 메서드를 사용하는 개발자가 보안 정책을 쉽게 이해할 수 있다.
  • 단점:
    • 보안 로직이 여러 메서드에 흩어지기 때문에 코드의 일관성이 떨어지고, 보안 설정이 분산될 수 있다. 이는 유지보수성 측면에서 어려움을 야기할 수 있다. 특히, 권한 설정이 변경될 경우 여러 메서드를 수정해야 할 수 있어 관리 비용이 증가한다.
    • @PreAuthorize를 남발하게 되면 비즈니스 로직과 보안 로직이 혼재되어 코드의 가독성이 떨어질 수 있다. 보안 관련 설정은 보통 한 곳에서 집중적으로 관리하는 것이 좋기 때문에, 메서드 단위로 분산되는 것은 오히려 혼란을 초래할 수 있다.

▶다른 개발자들의 의견

위 두 가지 방법에 대해 고민하면서, 다른 개발자들의 의견을 들을 수 있었다. 대부분의 개발자들은 첫 번째 방법SecurityConfig에서 경로별로 접근 권한을 제한하는 것을 선호했다. 그 이유는 보안 관련 책임을 한 곳에 집중시켜 관리하는 것이 더 명확하고 유지보수가 용이하기 때문이었다. @PreAuthorize를 사용하게 되면, 비즈니스 로직에서 접근 제어를 설정해야 하므로, 코드의 흐름을 파악하기 어려워질 수 있다는 단점이 있었다.

하지만, 예외적으로 보안이 매우 중요하고 민감한 메서드에 대해서는 @PreAuthorize를 사용하여 메서드 단위로 권한을 제한하는 것이 좋다는 의견도 있었다. 이 경우 특정 메서드에 대해 더 명확한 보안 설정을 적용할 수 있어 보안성을 높일 수 있다.


▶URL 경로 노출에 대한 고민

경로별 접근 제한을 설정할 때, /user/**와 같은 경로가 URL에 노출되는 것이 꺼려질 수 있다는 고민도 있었다. 특히 URL을 통해 어떤 권한이 필요한지 드러나는 것이 보안 측면에서 문제가 되지 않을까 생각하게 되었다. 이에 대해 다른 개발자의 의견을 참고해보니, 대부분의 경우 권한 정보가 노출되더라도 큰 문제는 없다는 것이었다. 보통 JWT 토큰에도 권한 정보가 포함되어 있고, 특정 권한을 가지지 않으면 요청을 처리할 수 없기 때문에, 권한 기반 인증에서 중요한 것은 권한 획득의 어려움이지, 권한이 노출되는지 여부가 아니라는 것이다.

만약 권한 정보를 URL에서 숨겨야 한다면, 경로별 권한 설정 대신 @PreAuthorize와 같은 어노테이션을 사용하여 메서드 단위로 권한을 제한하는 방법이 대안이 될 수 있다. 또한, 경로 정보를 배열에 저장하고 이를 통해 경로별로 권한을 관리하는 것도 고려할 수 있다.

private final String[] adminUrls = {"/api/post/create", "/api/post/delete"};

.requestMatchers(adminUrls).hasRole("ADMIN");

스프링 시큐리티에서 권한별 URL 접근을 제어하는 방법에는 여러 가지가 있지만, 각 방법의 장단점을 고려해야 한다. SecurityConfig에서 경로별로 접근 권한을 설정하는 방법은 보안 관련 로직을 한 곳에 모아 관리할 수 있어 코드의 가독성과 유지보수성 측면에서 유리하다. 반면에, @PreAuthorize를 사용하면 메서드 단위로 더 세밀한 접근 제어를 할 수 있지만, 보안 로직이 분산되어 코드의 흐름을 파악하기 어려워질 수 있다. 앞으로 개발을 진행하면서 @PreAuthorize 어노테이션을 사용하는 방법에 대해 더 깊이 있게 학습하고, 어떤 상황에서 이 방법이 적합한지 고민해 보고자 한다. 특히 보안이 중요한 메서드에 대해서는 @PreAuthorize를 사용하는 것이 보안성을 높일 수 있는 좋은 방법일 수 있다. 개발자로서 요구사항에 맞는 적절한 접근 제어 방법을 선택하고, 보안과 유지보수성 사이의 균형을 잘 맞춰 나가야겠다. 또한, URL에 권한 정보가 노출되는 것에 대한 고민도 필요할 때는 보안 정책을 재검토하고, 필요 시 다른 접근 제어 방식을 활용해 문제를 해결해야겠다.

'개발Article' 카테고리의 다른 글

[TIL]20241121 Jackson @JsonInclude  (1) 2024.11.21
[TIL]20241120 FACADE 패턴  (14) 2024.11.20
[TIL]20241117 TDD  (1) 2024.11.17
[TIL]20241116 @Data를 써도 될까?  (0) 2024.11.16
[TIL]20241115 소프트웨어에서 도메인이란?  (9) 2024.11.15