13장. URL 인가는 넓은 문을 닫는다
URL 규칙은 요청이 controller에 도착하기 전 1차 경계다. 구체적인 permit 목록 뒤에 anyRequest().authenticated() 또는 deny 정책을 둔다. 새 endpoint가 자동 공개되는 패턴을 피한다.
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/assets/**", "/error").permitAll()
.requestMatchers(HttpMethod.GET, "/api/catalog/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated());
하지만 /api/admin/** 역할 검사는 ACME와 OTHER의 자원을 구분하지 못한다. request 수준에서는 “이 종류의 endpoint에 접근 가능한가”를 거르고, service 수준에서 자원과 작업을 포함한 세밀한 정책을 적용한다. controller만 보호하면 batch, message consumer, 내부 호출이 우회할 수 있다.
경로 정규화, trailing slash, 대소문자, encoded slash, proxy prefix를 테스트한다. matcher와 MVC routing이 경로를 다르게 해석하면 우회가 생긴다. 관리 endpoint는 별도 port나 내부 네트워크, 별도 chain으로 분리하고 actuator 전체를 인터넷에 공개하지 않는다.