TIL

Authorize HTTP Request

Authorize HttpServletRequests with AuthorizationFilter

AuthorizationFilterFilterSecurityInterceptor를 대체한다.

```java
@Bean
SecurityFilterChain web(HttpSecurity http) throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().authenticated();
        )
        // ...

    return http.build();
}
```

- `AuthorizationManager` API를 간소화해서 사용할 수 있다.
- 재사용 및 커스텀도 간소화되었다.
- `Authentication` 조회를 지연시킴으로써 인가가 필요한 요청에만 `Authentication`을 조회한다.
- Bean-based 구성을 지원한다.

인가 흐름

img.png

  1. AuthorizationFilterSecurityContextHolder로부터 인증을 가져온다.
    1. 조회를 지연시키기 위해 Supplier로 래핑한다.
  2. AuthorizationManager에게 Suppler<Authentication>HttpServletRequest를 전달한다.
  3. 인가가 거절되면 AccessDeniedException이 발생된다.
    1. ExceptionTranslationFilter가 해당 예외를 처리한다.
  4. 인가가 성공하면 애플리케이션이 정상 처리될 수 있도록 FilterChain을 계속 진행한다.

Authorization Requests 설정

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		.authorizeHttpRequests(authorize -> authorize
			.requestMatchers("/resources/**", "/signup", "/about").permitAll()
			.requestMatchers("/admin/**").hasRole("ADMIN")
			.requestMatchers("/db/**").access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')"))
			// .requestMatchers("/db/**").access(AuthorizationManagers.allOf(AuthorityAuthorizationManager.hasRole("ADMIN"), AuthorityAuthorizationManager.hasRole("DBA")))
			.anyRequest().denyAll()
		);

	return http.build();
}

Request Matchers

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher("/api/**")
			.authorizeHttpRequests(authorize -> authorize
				.requestMatchers("/user/**").hasRole("USER")
				.requestMatchers("/admin/**").hasRole("ADMIN")
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher(antMatcher("/api/**"))                              
			.authorizeHttpRequests(authorize -> authorize
				.requestMatchers(antMatcher("/user/**")).hasRole("USER")         
				.requestMatchers(regexMatcher("/admin/.*")).hasRole("ADMIN")     
				.requestMatchers(new MyCustomRequestMatcher()).hasRole("SUPERVISOR")    
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}

public class MyCustomRequestMatcher implements RequestMatcher {

    @Override
    public boolean matches(HttpServletRequest request) {
        // ...
    }
}