2016-06-24 4 views
4

나는 SLIM 마이크로 프레임 워크로 API를 만들었습니다. 다음 코드를 사용하여 CORS 헤더를 추가하는 미들웨어를 설치했습니다.CORS 게시물 요청 실패

class Cors{ 

    public function __invoke(Request $request, Response $response, $next){ 

     $response = $next($request, $response); 
     return $response 
      ->withHeader('Access-Control-Allow-Origin', 'http://mysite') 
      ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization') 
      ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 
    } 

} 

프런트 엔드의 경우 VueJS를 사용했습니다. 설치 VueResource 및 다음 코드 사용하여 함수를 만들었습니다.

register (context, email, password) { 
    Vue.http({ 
    url: 'api/auth/register', 
    method: 'POST', 
    data: { 
    email: email, 
    password: password 
    } 
}).then(response => { 
    context.success = true 
}, response => { 
    context.response = response.data 
    context.error = true 
}) 
} 

크롬에서 다음 오류가 콘솔에 기록됩니다.

XMLHttpRequest cannot load http://mysite:9800/api/auth/register. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mysite' is therefore not allowed access. 

이상하게도 GET 요청은 완벽하게 작동합니다.

답변

2

여기 절반의 해결책이 있습니다.

누락 된 부분은이 헤더를 추가해야하는 OPTIONS 경로입니다.

+1

감사합니다 !!! 좋은 대답입니다, 친구. 이제 완벽하게 작동합니다. 나는 너없이 그것을 할 수 없었다. –

+0

@geggleto 제 지식에 따라 CORS의 경우 브라우저 클라이언트가 OPTIONS의 비행 요청을하기위한 위임장을 가지고 있으며 위에서 언급 한 응답 헤더의 유효성을 확인했습니다. OPTIONS를 비활성화하고 해당 헤더를 설정하지 않으면 오류가 발생한다는 의미입니까? 그런 요청을 할 때마다 response.Send (200);를 반환해야합니다. – xploreraj

1

이것은 프리 플라이트 요청이 OPTIONS 유형이기 때문에 발생합니다. 요청시 이벤트 리스너를 만들어야합니다.이 리스너는 형식을 확인하고 필요한 헤더가 포함 된 응답을 보냅니다.

슬림 프레임 워크를 알지 못하지만, Symfony의 실제 예제가 있습니다.

// Headers allowed to be returned. 
const ALLOWED_HEADERS = ['Authorization', 'Origin', 'Content-Type', 'Content-Length', 'Accept']; 

을 그리고 요청 리스너에 들어오는 모든 요청을 감시하는 onKernelRequest 방법있다 :

먼저 헤더의 예는 반환되는

여기
/** 
    * @param GetResponseEvent $event 
    */ 
    public function onKernelRequest(GetResponseEvent $event) 
    { 
     // Don't do anything if it's not the master request 
     if (!$event->isMasterRequest()) { 
      return; 
     } 

     // Catch all pre-request events 
     if ($event->getRequest()->isMethod('OPTIONS')) { 
      $router = $this->container->get('router'); 
      $pathInfo = $event->getRequest()->getPathInfo(); 

      $response = new Response(); 
      $response->headers->set('Access-Control-Allow-Origin', $event->getRequest()->headers->get('Origin')); 
      $response->headers->set('Access-Control-Allow-Methods', $this->getAllowedMethods($router, $pathInfo)); 
      $response->headers->set('Access-Control-Allow-Headers', implode(', ', self::ALLOWED_HEADERS)); 
      $response->headers->set('Access-Control-Expose-Headers', implode(', ', self::ALLOWED_HEADERS)); 
      $response->headers->set('Access-Control-Allow-Credentials', 'true'); 
      $response->headers->set('Access-Control-Max-Age', 60 * 60 * 24); 
      $response->send(); 
     } 
    } 

난 그냥 재현을 Origin (모든 도메인은 리소스를 요청할 수 있으므로 도메인으로 변경해야합니다). 희망 사항에 따라 일부 접착제가 제공되기를 바랍니다.

+0

상세하고 철저히 설명 된 답변을 주셔서 감사합니다.하지만이 솔루션은 실패했습니다. –

2

실제로 CORS는 브라우저 수준에서 구현됩니다. 심지어 함께

return $response 
      ->withHeader('Access-Control-Allow-Origin', 'http://mysite') 
      ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization') 
      ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 

크롬과 모질라는 교차 원점을 허용하도록 헤더를 설정하지 않습니다. 그 해제 그래서, 당신은 강제로 필요 ..

가 비활성화 CORS

Disable same origin policy in Chrome

+0

이 답변에 대한 추가 정보 ... 비행 전 요구 사항을 처리하려면 실제 HTTP 동사 외에 OPTIONS도 받아 들여야합니다. – geggleto

+0

더 자세히 설명해 주시겠습니까? @geggleto –

+0

비록 프로덕션에서 사용하고 싶습니다. –

1

CORS가 설정에 어려울 수 있습니다에 대한 자세한 내용을 읽어 보시기 바랍니다. 핵심은 서버와 클라이언트에서 특수 헤더를 설정해야한다는 것이며, 내가 알기까지 Vue 헤더 세트가 표시되지 않는다는 것입니다. http은 기능이 아닙니다. 그러나 게시 요청에 대한 설정이 여기에 있습니다. 당신이 당신의 데이터를 캐릭터 라인 화해야하고 일반적으로 Access-Control-Allow-Origin 헤더를 포함하여 헤더를 노출 할 필요가

const data = { 
    email: email, 
    password: password 
    } 
const options = { 
    headers: { 
     'Access-Control-Expose-Headers': // all of your headers, 
     'Access-Control-Allow-Origin': '*' 
    } 
} 
Vue.http.post('api/auth/register', JSON.stringify(data), options).then(response => { 
    // success 
}, response => { 
    // error 
}) 

알 수 있습니다. 내 앱 중 하나에서 수행 한 작업은 인터셉터를 정의하는 것이므로 모든 요청에 ​​대해 헤더를 설정할 필요가 없습니다.

Vue.http.headers.common['Access-Control-Expose-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, x-session-token, timeout, Content-Length, location, *' 
Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'