1. 개요
이 짧은 사용방법(예제)에서는 교차 출처 통신을 지원하고 Spring Security를 사용하는 애플리케이션에서 발생할 수 있는 "프리플라이트에 대한 응답에 잘못된 HTTP 상태 코드 401이 있습니다" 오류를 해결하는 방법을 배울 것입니다.
먼저 교차 출처 요청이 무엇인지 확인한 다음 문제가 있는 예를 수정합니다.
2. 교차 출처 요청
간단히 말해 Cross-Origin 요청은 요청의 출처와 대상이 다른 HTTP 요청입니다. 예를 들어, 웹 애플리케이션이 한 도메인에서 제공되고 브라우저가 AJAX 요청을 다른 도메인의 서버로 보내는 경우입니다.
교차 출처 요청을 관리하려면 서버에서 CORS 또는 교차 출처 리소스 공유로 알려진 특정 메커니즘을 활성화해야 합니다.
CORS의 첫 번째 단계는 요청 대상이 지원하는지 여부를 결정 하는 OPTIONS 요청입니다. 이를 비행 전 요청이라고 합니다.
그런 다음 서버는 헤더 모음으로 비행 전 요청에 응답할 수 있습니다.
- Access-Control-Allow-Origin : 리소스에 액세스할 수 있는 출처를 정의합니다. '*'는 모든 출처를 나타냅니다.
- Access-Control-Allow-Methods : 교차 출처 요청에 대해 허용되는 HTTP 방법을 나타냅니다.
- Access-Control-Allow-Headers : 교차 출처 요청에 대해 허용된 요청 헤더를 나타냅니다.
- Access-Control-Max-Age : 캐시된 실행 전 요청 결과의 만료 시간을 정의합니다.
따라서 비행 전 요청이 이러한 응답 헤더에서 결정된 조건을 충족하지 않으면 실제 후속 요청에서 교차 출처 요청과 관련된 오류가 발생합니다.
Spring 기반 서비스에 CORS 지원 을 추가하는 것은 쉽지만 잘못 구성된 경우 이 비행 전 요청은 항상 401과 함께 실패합니다.
3. CORS 지원 REST API 생성
문제를 시뮬레이션하기 위해 먼저 교차 출처 요청을 지원하는 간단한 REST API를 생성해 보겠습니다.
@RestController
@CrossOrigin("http://localhost:4200")
public class ResourceController {
@GetMapping("/user")
public String user(Principal principal) {
return principal.getName();
}
}
@CrossOrigin 어노테이션은 API가 인수에 언급된 출처에서만 액세스할 수 있도록 합니다.
4. REST API Security
이제 Spring Security를 사용하여 REST API를 보호해 보겠습니다.
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
return http.build();
}
}
이 구성 클래스에서는 모든 수신 요청에 대한 권한 부여를 시행했습니다. 결과적으로 유효한 인증 토큰이 없는 모든 요청을 거부합니다.
5. 비행 전 요청하기
이제 REST API를 만들었으므로 curl 을 사용하여 비행 전 요청을 시도해 보겠습니다 .
curl -v -H "Access-Control-Request-Method: GET" -H "Origin: http://localhost:4200"
-X OPTIONS http://localhost:8080/user
...
< HTTP/1.1 401
...
< WWW-Authenticate: Basic realm="Realm"
...
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: http://localhost:4200
< Access-Control-Allow-Methods: POST
< Access-Control-Allow-Credentials: true
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
...
이 명령의 출력 에서 요청이 401로 거부되었음을 알 수 있습니다.
이것은 curl 명령이므로 출력에 "Response for preflight has invalid HTTP status code 401" 오류가 표시되지 않습니다.
그러나 다른 도메인에서 REST API를 사용하는 프런트 엔드 애플리케이션을 만들고 브라우저에서 실행하여 이 정확한 오류를 재현할 수 있습니다.
6. 솔루션
우리는 Spring Security 구성에서 승인에서 프리플라이트 요청을 명시적으로 제외하지 않았습니다 . Spring Security는 기본적으로 모든 엔드포인트를 보호한다는 것을 기억하십시오.
결과적으로 API는 OPTIONS 요청에서도 인증 토큰을 예상합니다.
Spring은 권한 검사에서 OPTIONS 요청을 제외하는 즉시 사용 가능한 솔루션을 제공합니다.
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// ...
http.cors();
return http.build();
}
}
cors () 메소드는 OPTIONS 요청에 대한 인증 검사를 우회하여 Spring 제공 CorsFilter 를 애플리케이션 컨텍스트에 추가합니다.
이제 애플리케이션을 다시 테스트하고 작동하는지 확인할 수 있습니다.
7. 결론
이 짧은 기사에서 Spring Security 및 cross-origin 요청과 연결된 "응답에 잘못된 HTTP 상태 코드 401이 있습니다."라는 오류를 수정하는 방법을 배웠습니다.
예제에서 클라이언트와 API는 문제를 재현하기 위해 다른 도메인 또는 포트에서 실행되어야 합니다. 예를 들어 로컬 시스템에서 실행할 때 기본 호스트 이름을 클라이언트에 매핑하고 시스템 IP 주소를 REST API에 매핑할 수 있습니다.
항상 그렇듯이 이 사용방법(예제)에 표시된 예제는 Github 에서 찾을 수 있습니다 .