Google Sign In与后端Auth:客户端正常,服务端报500及连接拒绝问题
触发错误的直接原因(按优先级排序)
后端代码致命错误(直接触发500)
config.php未定义$CLIENT_ID、$CLIENT_SECRET两个变量,直接调用会抛出致命错误;若本地PHP关闭了错误提示,所有这类错误会直接转为500响应createJSON.php变量名错配:config.php初始化的Google Client实例是$google_client,代码中调用fetchAccessTokenWithAuthCode时用了未定义的$client变量createJSON.php类名拼写错误:Google_Service_0auth2中用了数字0,正确类名是Google_Service_Oauth2(首字母为字母O)createJSON.php数组下标未加引号:$data[email]会被PHP解析为未定义常量,抛出错误
连接被拒绝的原因
- axios请求地址写死了
localhost:80,如果本地Web服务器(Apache/Nginx)未运行在80端口,或服务未启动,会直接触发ERR_CONNECTION_REFUSED
流程逻辑错误(就算解决了500也会跑不通)
- 参数传错:前端Google Sign-In SDK默认返回的是
tokenId(ID令牌),但后端fetchAccessTokenWithAuthCode方法需要的是授权码(Authorization Code),两者是OAuth流程中完全不同的凭证,无法通用 - 跨域配置错误:
Access-Control-Allow-Origin是后端需要返回的响应头,放在请求头里完全无效,浏览器会直接拦截跨域请求 - 流程混淆:
config.php中配置的redirect_uri是纯后端渲染应用走OAuth重定向流程用的,你现在是前后端分离架构,走前端SDK登录的流程,这个配置完全无效,且如果和Google控制台配置不一致还会触发额外报错
修正后的实现步骤
1. Google云控制台前置配置
- 把你的前端开发地址(比如
http://localhost:3000)、后端地址(比如http://localhost:8080)添加到授权来源列表 - 不需要把前端地址添加到授权重定向URI,因为当前流程不需要走服务端重定向登录
2. 修正后的后端代码
修正后的config.php
<?php session_start(); require_once('../vendor/autoload.php'); // 替换为你自己的Google OAuth凭证 $CLIENT_ID = '你的Google客户端ID'; $CLIENT_SECRET = '你的Google客户端密钥'; $google_client = new Google_Client(); $google_client->setClientId($CLIENT_ID); $google_client->setClientSecret($CLIENT_SECRET); $google_client->addScope('email'); $google_client->addScope('profile');
修正后的createJSON.php
前后端分离场景下不需要走授权码换token流程,直接验证前端传的ID Token即可:
<?php // 先返回CORS响应头,解决跨域问题 header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Methods: POST, GET, OPTIONS"); header("Access-Control-Allow-Headers: Content-Type"); // 处理浏览器跨域预检请求 if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { exit(0); } include('config.php'); // 接收前端传的ID Token if (isset($_POST['id_token'])) { // 直接验证ID Token合法性,不需要调用授权码换token的方法 $payload = $google_client->verifyIdToken($_POST['id_token']); if ($payload) { // 验证通过,直接从token payload中拿到用户信息 $_SESSION['user_email'] = $payload['email']; $_SESSION['user_name'] = $payload['name']; $_SESSION['user_avatar'] = $payload['picture']; // 返回成功响应 echo json_encode([ 'status' => 'success', 'user' => [ 'email' => $payload['email'], 'name' => $payload['name'] ] ]); exit; } else { echo json_encode(['status' => 'error', 'message' => '无效的ID Token']); exit; } }
3. 修正后的前端代码
const responseGoogle = response => { setName(response.profileObj.name); setUrl(response.profileObj.imageUrl); // 传ID Token,和后端参数对应 const postData = { id_token: response.tokenId }; axios({ method: 'POST', // 替换为你实际后端服务的地址和端口,不要写死80端口 url: "http://localhost:你的后端实际端口/php/createJSON.php", headers: { "Content-Type": "application/json" }, data: postData }) .then((response) => { console.log('后端会话创建成功', response.data); }, (error) => { console.log('请求失败', error); }); }
关键注意事项
- 不要混用两套OAuth流程:前端SDK + ID Token验证适合前后端分离架构,授权码换token流程适合纯后端渲染应用,两者不要交叉使用
- 本地调试时先开启PHP错误提示(把
php.ini里的display_errors设为On),直接查看具体错误原因,不要只看500状态码排查 - 确保后端服务端口和axios请求的端口完全一致,避免连接被拒绝
内容的提问来源于stack exchange,提问作者Ozbodd
相关产品推荐
相关产品推荐

