Spring Security ‐ 인가 프로세스 - dnwls16071/Backend_Summary GitHub Wiki
📚 요청 기반 권한 부여 (1) - HttpSecurity.authorizeHttpRequests()
- Spring Security는 요청 기반 권한 부여와 메서드 기반 권한 부여를 통해 리소스에 대한 심층적인 방어를 제공한다.
- 요청 기반 권한 부여는 클라이언트 측 요청 즉, HttpServletRequest에 대한 권한 부여를 말한다.
authorizeHttpRequests()는 사용자 자원 접근을 위한 요청 엔드포인트와 접근에 필요한 권한을 매핑시키기 위한 규칙이다. 엔드포인트에 접근하려면authorizeHttpRequests()에 해당 규칙들이 모두 포함되어야 한다.authorizeHttpRequests()을 통해 요청과 권한 규칙이 설정되면 내부적으로 AuthorizationFilter가 요청에 대한 권한 작업을 수행한다.
requestMatchers()
- requestMatchers 메소드는 HTTP 요청의 URL 패턴, HTTP 메소드, 요청 파라미터 등을 기반으로 어떤 요청에 대해서는 특정 보안 설정을 적용하고 다른 요청에 대해서는 적용하지 않도록 세밀하게 제어할 수 있게 해준다.
❗Spring Security는 클라이언트 요청에 대해 위에서부터 아래로 나열된 순서대로 처리하며 요청에 대해 첫 번째 일치만 적용된다. ❗예를 들어,
/admin/**가/admin/db요청을 포함하므로 의도한 대로 권한 규칙이 올바르게 적용되지 않을 수 있다. 그렇기 때문에 엔드포인트를 정의할 때 좁은 범위의 경로를 먼저 정의하고 이후에 큰 범위 경로를 정의해야 한다.
- 권한 규칙은 내부적으로 AuthorizationManager 클래스에 의해 재구성되며 모든 요청은 여러 종류의 AuthorizationMaanger에 의해 승인 혹은 거부된다.
📚 표현식 및 커스텀 권한 구현 방법
- Spring Security는 표현식을 사용해서 권한 규칙을 설정하도록 WebExpressionAuthorizationMaanger를 제공한다.
- 표현식은 시큐리티가 제공하는 권한 규칙을 사용하거나 사용자가 표현식을 커스텀으로 구성할 수 있다.
requestMatchers().access(new WebExpressionAuthorizationManager("expression"))
📚 요청 기반 권한 부여 (2) - HttpSecurity.securityMatcher()
- securityMatcher는 특정 패턴에 해당하는 요청에만 보안 규칙을 적용할 수 있도록 설정하는 것으로 중복해서 정의하면 마지막에 설정한 것으로 대체한다.
- securityMatchers 메소드는 특정 패턴에 해당하는 요청을 단일이 아닌 다중 설정으로 구성해서 보안 규칙을 적용할 수 있다.
📚 메서드 기반 권한 부여 - @PreAuthorize, @PostAuthorize
- Spring Security는 요청 수준 권한뿐만 아니라 메서드 수준에서의 권한 부여도 지원한다.
- 메서드 수준 권한 부여를 활성화하려면 설정 클래스에
@EnableMethodSecurity어노테이션을 추가해야 한다. - SpEL(Spring Expression Language) 표현식을 사용해 다양한 보안 조건을 정의할 수 있다.
@PreAuthorize
- 메서드가 실행되기 전에 특정 보안 조건이 충족되는지 확인하는 데 사용되며 보통 서비스 또는 컨트롤러 메서드에 적용되어 해당 메서드가 호출되기 전에 사용자 인증 정보와 권한을 검사한다.
@PostAuthorize
- @PreAuthorize 어노테이션과 달리 메서드가 실행된 후 보안 검사를 수행하는데 사용된다.
- 메서드 실행 후 결과에 대한 보안 조건을 검사해 특정 조건을 만족하는 경우에만 사용자가 결과를 받을 수 있도록 한다.
📚 메서드 기반 권한 부여 - @PreFilter, @PostFilter
@PreFilter
- 메서드가 실행되기 전에 메서드에 전달된 컬렉션 타입의 파라미터에 대한 필터링을 수행하는데 사용된다.
- 주로 사용자가 보낸 컬렉션 내의 객체들을 특정 기준에 따라 필터링하고 그 중 보안 조건을 만족하는 객체들에 대해서만 메서드가 처리하도록 할 때 사용한다.
@PostFilter
- 메서드가 반환하는 컬렉션 타입의 결과에 대해 필터링을 수행하는 데 사용된다.
- 메서드가 컬렉션을 반환할 때 반환되는 각 객체가 특정 보안 조건을 충족하는지 확인하고 조건을 만족하지 않는 객체들을 결과에서 제거한다.
📚 메서드 기반 권한 부여 - @Secured, JSR-250 부가 기능
@Secured
- @Secured 어노테이션을 메서드에 적용하면 지정된 권한을 가진 사용자만 해당 메서드를 호출할 수 있으며 더 풍부한 형식을 지원한다.
- @Secured 어노테이션을 사용하려면 Spring Security 설정에서
@EnableMethodSecurity(securedEnabled=true)설정을 활성화해야한다.
JSR-250
- JSR-250 기능을 적용하면 @RolesAllowed, @PermitAll 및 @DenyAll 어노테이션 보안 기능이 활성화된다.
- JSR-250 어노테이션을 사용하려면 Spring Security 설정에서
@EnableMethodSecurity(jsr250Enabled=true)설정을 활성화해야한다.
❗기본적으로 모든 메서드는 클래스 수준의 권한 처리 동작을 상속받는다. ❗메서드에 어노테이션을 선언한 메서드는 클래스 수준의 어노테이션을 덮어쓰게 된다. ❗인터페이스에 동일한 규칙이 적용되지만 클래스가 2개의 다른 인터페이스로부터 동일한 메서드의 어노테이션을 상속받는 경우에는 시작할 때 실패한다. 그래서 구체적인 메서드에 어노테이션을 추가해 모호함을 해결할 수 있다.
📚 정적 자원 관리 방법
- Spring Security에서 RequestMatcher 인스턴스를 등록해서 무시해야 할 요청을 지정할 수 있다.
- 주로 정적 자원에 대한 요청이나 특정 엔드포인트가 보안 필터를 거치지 않도록 설정해야할 때 사용된다.
- 이전에는 모든 요청마다 세션을 확인해야해서 성능 저하가 수반되었으나 Spring Security 6.x부터 권한 부여 규칙에서 필요한 경우를 제외하고는 세션을 확인하지 않는다.
- 성능 문제가 해결되었기 때문에 모든 요청에 대해서 permitAll을 사용할 것을 권장하며 정적 자원에 대한 요청일지라도 안전한 헤더를 작성할 수 있어 더 안전하다.
📚 계층적 권한 - RoleHireachy
- 기본적으로 Spring Security에서 권한과 역할은 계층적이거나 상하 관계로 구분되지 않는다. 그래서 인증 주체가 다양한 역할과 권한을 부여 받아야만 한다.
- RoleHireachy는 역할 간 계층 구조를 정의하고 관리하는 데 사용되며 보다 간편하게 역할 간 계층 구조를 설정하고 이를 기반으로 사용자의 액세스 규칙을 정의할 수 있다.
- ROLE_A를 가진 사용자는 ROLE_B, ROLE_C, ROLE_D도 가진다.
- ROLE_B를 가진 사용자는 ROLE_C, ROLE_D를 가진다.
- ROLE_C를 가진 사용자는 ROLE_D를 가진다.
- 계층적 역할을 사용하면 액세스 규칙이 크게 줄어들 뿐만 아니라 더 간결하고 우아한 형태로 규칙을 표현할 수 있다.
- 허나 만약 세분화된 권한 배분이 필요하다면 해당 방식은 적합하지 않을 수 있다.
@Bean
static RoleHierarchy roleHierarchy() {
return RoleHierarchyImpl.fromHierarchy("ROLE_ADMIN > permission:read");
}
- setHirerachy : 역할 계층을 설정하고 각 역할에 대해 해당 역할의 하위 계층에 속하는 모든 역할 집합을 미리 정해놓는다.
- 역할 계층 예시 : ROLE_A > ROLE_B > ROLE_C
- getReachableGrantedAuthorities
- 모든 도달 가능한 권한의 배열을 반환한다.
- 도달 가능한 권한은 직접 할당된 권한에 더해 역할 계층에서 이들로부터 도달 가능한 모든 권한을 의미한다.
- 예시 : 직접 할당된 권한이 ROLE_B라면 도달 가능한 권한은 ROLE_B, ROLE_C이다.