주의
이 책은 Spring Security 5 버전을 기준으로 작성되었으므로, Spring Boot 3.X 버전에서는 일부 클래스가 더 이상 사용되지(deprecated) 않을 수 있습니다.
1. Authorization
- 권한 부여 (Authorization)는 식별된 클라이언트가 요청된 리소스에 접근할 권한이 있는지 시스템이 결정하는 프로세스
- 스프링 시큐리티에서 애플리케이션은 인증 흐름을 완료한 뒤 요청을 권한 부여 필터에 위임함
- 필터는 구성된 권한 부여 규칙에 따라 요청을 허용하거나 거부함

2. 권한과 역할에 따라 접근 제한
- 사용자는 가진 권한에 따라 특정 작업만 실행할 수 있음
- 권한은 사용자가 시스템 리소스로 수행할 수 있는 작업이며 권한의 이름은 객체의 getAuthority()가 String 형식으로 반환하는 값에서 얻을 수 있음
- 권한의 이름은 맞춤형 권한 부여 규칙을 정의할 때 필요하며 권한 부여 규칙은 다음과 같음
- 제인은 제품 레코드를 삭제할 수 있음 (허가된 권한 DELETE)
- 존은 문서 레코드 읽을 수 있음 (허가된 권한 READ)
- 애플리케이션은 사용자 제인과 존이 읽기, 쓰기 및 삭제와 같은 이름의 작업을 수행할 수 있게 해 줌
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface GrantedAuthority extends Serializable { | |
String getAuthority(); | |
} |
- 스프링 시큐리티의 사용자를 나타내는 계약인 UserDetails는 GrantedAuthority 인스턴스의 컬렉션을 가짐
- 한 사용자는 하나 잇아의 이용 권리를 가질 수 있으며 getAuthorities() 메서드는 GrantedAuthority 인스턴스의 컬렉션을 반환
- UserDetails 내 getAuthorities() 메서드를 통해 사용자에게 허가된 모든 권한을 조회 가능
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface UserDetails extends Serializable { | |
Collection<? extends GrantedAuthority> getAuthorities(); | |
// 중략 | |
} |

2.1 사용자 권한을 기준으로 모든 엔드포인트에 접근 제한
- 사용자의 권한을 기반으로 엔드포인트에 대한 접근을 구성하는 방법은 세 가지가 있음
- hasAuthority(): 애플리케이션이 제한을 구성하는 하나의 권한만 매개변수로 받으며 해당 권한이 있는 사용자만 엔드포인트 호출 가능
- hasAnyAuthority(): 애플리케이션이 제한을 구성하는 권한을 하나 이상 받을 수 있으며 사용자는 요청하려면 지정된 권한 중 하나라도 있어야 함
- access(): SpEL을 기반으로 권한 부여 규칙을 구축하므로 액세스를 구성하는 데 무한한 가능성이 있지만 코드를 읽고 디버그 하기 어려운 단점이 있음 (추천하지 않는 방법)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
public class ProjectConfig extends WebSecurityConfigurerAdapter { | |
@Override | |
@Bean | |
public UserDetailsService userDetailsService() { | |
var manager = new InMemoryUserDetailsManager( | |
var user1 = User.withUsername("john") | |
.password("12345") | |
.authorities("READ") | |
.build(); | |
var user2 = User.withUsername("jane") | |
.password("12345") | |
.authorities("WRITE") | |
.build(); | |
manager.createUser(user1); | |
manager.createUser(user2); | |
return manager; | |
} | |
@Bean | |
public PasswordEncoder passwordEncoder() { | |
return NoOpPasswordEncoder.getInstance(); | |
} | |
@Override | |
protected void configure(HttpSecurity http) throws Exception { | |
http.httpBasic(); | |
// WRITE 및 READ 권한이 있는 사용자의 요청을 모두 허용 | |
http.authorizeRequests().anyRequest().hasAnyAuthority("WRITE", "READ"); | |
// 사용자가 엔드포인트에 접근하기 위한 조건 지정 | |
// http.authorizeRequests().anyRequest().hasAuthority("WRITE"); | |
// hasAuthority 또는 hasAnyAuthority() 메서드를 적용할 수 없을 때 최후의 수단으로만 권장 | |
// 하지만 매개변수로 지정하는 식으로 규칙을 유연하게 구성할 수 있다는 장점은 있음 | |
// 사용자에게 읽기 권한이 있어야 하지만 삭제 권한은 없어야 | |
// Spring expression = "hasAuthority('READ') and !hasAuthority('DELETE')"; | |
// http.authorizeRequests().anyRequest().access(expression); | |
} | |
} |
2.2 사용자 역할 (Role)을 기준으로 모든 엔드포이니트에 대한 접근 제한
- 역할은 사용자가 착용하는 배지와 비슷하며 사용자에게 작업 그룹에 속한 이용 권리를 제공
- 일부 애플리케이션은 특정 사용자에게 항상 같은 권한 그룹을 제공
- i.g. 사용자가 읽기 권한만 가지거나 읽기, 쓰기, 삭제의 모든 권한을 가진다면 사용자는 읽기 권한만 있는 독자 역할이나 읽기, 쓰기, 삭제 권한이 있는 관리자 역할 중 하나를 가진다고 생각하면 이해하기 쉬움
- 역할 이름은 권한 이름과 마찬가지로 개발자가 선택 가능
- 내부적으로 역할도 스프링 시큐리티에서 같은 GrantedAuthority 계약으로 나타냄
- 역할을 정의할 때 역할 이름은 ROLE_ 접두사로 시작해야 함
- 사용자 역할에 대한 제약 조건을 설정하기 위해 다음 메서드 중 하나를 이용할 수 있음
- hasRole(): 애플리케이션이 요청을 승인할 하나의 역할 이름을 매개변수로 받음
- hasAnyRole(): 애플리케이션이 요청을 승인할 여러 역할 이름을 매개변수로 받음
- access(): 애플리케이션의 요청을 승인할 역할을 스프링 식으로 지정, 역할을 지정하는 데는 hasRole() 또는 hasAnyRole()을 SpEL 식으로 이용 가능
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
public class ProjectConfig extends WebSecurityConfigurerAdapter { | |
@Override | |
@Bean | |
public UserDetailsService userDetailsService() { | |
var manager = new InMemoryUserDetailsManager(); | |
var user1 = User.withUsername("john") | |
.password("12345") | |
.roles("ADMIN") | |
.build(); | |
var user2 = User.withUsername("jane") | |
.password("12345") | |
.roles("MANAGER") | |
.build(); | |
manager.createUser(user1); | |
manager.createUser(user2); | |
return manager; | |
} | |
@Bean | |
public PasswordEncoder passwordEncoder() { | |
return NoOpPasswordEncoder.getInstance(); | |
} | |
@Override | |
protected void configure(HttpSecurity http) throws Exception { | |
http.httpBasic(); | |
// hasRole() 메서드는 엔드포인트에 접근할 수 있는 역할을 지정 | |
// 여기에 ROLE_접두사는 나오지 않는 것에 주의 | |
http.authorizeRequests().anyRequest().hasRole("ADMIN"); | |
} | |
} |
2.3 모든 엔드포인트에 대한 접근 제한
- permitAll() 메서드로 모든 요청에 대한 액세스를 허용할 수 있으며 권한과 역할을 기준으로 접근 규칙을 적용할 수 있음
- 반대로 denyAll() 메서드를 통해 모든 요청을 거부할 수도 있음
- 실제 애플리케이션에서는 종종 이상하게 보일 수 있는 다양한 아키텍처 요구 사항을 해결해야 하며 프레임워크는 어떤 상황이라도 해결할 수 있는 유연성을 제공해야 하기 때문에 denyAll() 메서드는 다른 모든 옵션과 마찬가지로 중요함

참고
스프링 시큐리티 인 액션
반응형
'Spring > 스프링 시큐리티 인 액션' 카테고리의 다른 글
[10장] CSRF 보호와 CORS 적용 (0) | 2025.05.31 |
---|---|
[8장] 권한 부여 구성: 제한 적용 (0) | 2025.05.30 |
[5장] 인증 구현 (0) | 2025.05.21 |
[4장] 암호 처리 (0) | 2025.05.19 |
[3장] 사용자 관리 (0) | 2025.05.18 |