我遇到了一个重大问题。我使用symfony 3开发了一个api。使用React在前端查询此api。背面(API)使用的服务器为http://127.0.0.1:8000。前端使用的服务器是http://localhost:3000。
从前端调用api时,出现两个错误: -405方法不允许 -已通过以下方式阻止从原点“ http://127.0.0.1:8000/users/email/settings”访问“ http://localhost:3000”处的XMLHttpRequest:CORS策略:对预检检查的响应:请求中不存在“ Access-Control-Allow-Origin”标头资源。
但是,我指定了正确的方法(补丁)并通过API配置了标头:
这是详细的代码:
API(带有symfony支持)
/**
* @Route("/users/email/settings", methods={"PATCH"})
* @param Request $request
* @param FlashMessage $flashMessage
*/
public function usersEmailEditAction(Request $request, FlashMessage $flashMessage)
{
if($request->getContent())
{
$data = json_decode($request->getContent(), true);
$em = $this->getDoctrine()->getManager();
$user = $this->get('security.token_storage')->getToken()->getUser();
$editUser = $em->getRepository(User::class)->find($user->getId());
if (!$editUser) {
return $flashMessage->messageError("USER_NOT_FOUND", 1);
}
if (!$data['password']) {
return $flashMessage->messageError("PASSWORD_NOT_FOUND", 1);
}
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
return $flashMessage->messageError("INVALID_EMAIL", 1, "format email invalid");
}
if (!filter_var($data['confirmEmail'], FILTER_VALIDATE_EMAIL)) {
return $flashMessage->messageError("INVALID_EMAIL", 1, "format email invalid");
}
if ($data['email'] != $data['confirmEmail']) {
return $flashMessage->messageError("NO_MATCHING_EMAIL", 1, "les emails sont différents");
}
// on vérifie le mot de passe
$encoder = $this->get('security.password_encoder');
$isPasswordValid = $encoder->isPasswordValid($user, $data['password']);
// Le mot de passe n'est pas correct
if (!$isPasswordValid) {
return $flashMessage->messageError("INCORRECT_PASSWORD", 1);
}
$editUser->setEmail($data['email']);
$editUser->setUpdatedAt(new \DateTime());
$em->flush();
return $flashMessage->messageSuccess("EMAIL_UPDATED_SUCCESSFULLY", 0);
}else {
return $flashMessage->messageWarning("NOTHING_UPDATED", 2);
}
}
返回$ flashMessage
public function messageSuccessAction($message, $code, $desc = null)
{
$response = new Response();
$response->setContent(json_encode([
'error' => $code,
'message' => $message
]));
$response->headers->set('Content-Type', 'application/json');
$response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS');
return $response;
//return new JsonResponse(array("error" => $code, "message" => $message));
}
public function messageErrorAction($message, $code, $desc = null)
{
$response = new Response();
$response->setContent(json_encode([
'error' => $code,
'message' => $message
]));
$response->headers->set('Content-Type', 'application/json');
$response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS');
return $response;
//return new JsonResponse(array("error" => $code, "message" => $message));
}
public function messageWarningAction($message, $code, $desc = null)
{
$response = new Response();
$response->setContent(json_encode([
'error' => $code,
'message' => $message
]));
$response->headers->set('Content-Type', 'application/json');
$response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS');
return $response;
//return new JsonResponse(array("error" => $code, "message" => $message));
}
从Front请求API(使用Axios)
requestAPI = (myPassword, newEmail, confirmEmail) => {
axios.patch('http://127.0.0.1:8000/users/email/settings', {
crossdomain: true,
password: myPassword,
email: newEmail,
confirmEmail: confirmEmail
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
我也尝试了没有跨网域,但是没有。
你有什么主意吗?谢谢您的帮助
答案 0 :(得分:0)
是否有405 Method Not Allowed
通话获得了OPTIONS
的通话?也称为"preflight request"。
对于您的所有CORS需求,您都应该包括NelmioCorsBundle,它很容易配置,并且您不需要设置自己的CORS标头。
这里发生的是,您的浏览器将首先通过OPTIONS
调用检查服务器是否理解CORS协议。但是您的应用程序并没有回答这一问题,至少没有正确的CORS标头,因此您的PATCH
调用永远不会被浏览器发出。错误消息甚至如此。 “响应飞行前检查:所请求的资源上没有'Access-Control-Allow-Origin'标头。”