如何在Google Sign In中向PHP验证器传递JWT Token并完成验证?
问题:PHP集成Google Sign In后端验证失败
背景
网站原本仅支持8-9位用户编号+4位PIN码登录,现在要集成企业邮箱的Google Sign In提升安全性。目前前端Google登录按钮已可正常触发登录,能获取用户邮箱信息,但后端verifier.php无法完成JWT验证,不清楚正确的实现方式。
前端测试代码(已可获取用户信息)
<script src="https://accounts.google.com/gsi/client" async defer></script> <div id="g_id_onload" data-client_id="xxxxxx.apps.googleusercontent.com" data-auto_select="false" data-itp_support="true" data-auto_prompt="false" data-ux_mode="redirect" data-login_uri="http://localhost/verifier.php" data-hd="xxx" data-locale="vi"> </div> <div class="g_id_signin" data-type="standard" data-shape="pill" data-theme="outline" data-text="continue_with" data-size="large" data-locale="vi" data-logo_alignment="left"> </div> <p id="account"></p> </body> <script> function handleCredentialResponse(response) { const responsePayload = decodeJwtResponse(response.credential); console.log('ID: '+responsePayload.sub); console.log('Name: ' + responsePayload.name); console.log('Email: ' + responsePayload.email); var username = responsePayload.email.split('@')[0]; console.log(username); document.getElementById('account').innerHTML='welcome '+ responsePayload.name+' /// '+username; } function decodeJwtResponse(token) { var base64Url = token.split(".")[1]; var base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/"); var jsonPayload = decodeURIComponent( atob(base64) .split("") .map(function (c) { return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2); }) .join("") ); return JSON.parse(jsonPayload); } </script>
注:上述脚本仅用于测试,可正确获取用户邮箱及用户名
当前后端代码(无法运行)
<?php require_once 'C:\xampp\htdocs\google-api-php-client--PHP8.0\vendor\autoload.php'; $CLIENT_ID= 'xxxxx.apps.googleusercontent.com' $id_token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjFhYWU4ZDdjOTIwNThiNWVlYTQ1Njg5NWJmODkwODQ1NzFlMzA2ZjMiLCJ0eXAiOiJKV1QifQ // Get $id_token via HTTPS POST. $client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken($id_token); if ($payload) { $userid = $payload['sub']; // If request specified a G Suite domain: //$domain = $payload['hd']; } else { // Invalid ID token } ?>
错误信息
Parse error: syntax error, unexpected variable "$id_token" in C:\xampp\htdocs\verifier.php on line 4
解决方案
1. 修复语法错误
原代码存在两处基础语法问题:
- 第2行
$CLIENT_ID赋值末尾缺少分号; - 第3行
$id_token的赋值语法错误,PHP中变量赋值用=而非:,且不能直接写死测试token,需从请求中获取
2. 正确获取$id_token
由于前端设置了data-ux_mode="redirect",Google登录成功后会将JWT Token以credential参数通过GET请求传递到verifier.php,因此需要从$_GET['credential']中获取。
3. 完整可运行的verifier.php代码
<?php session_start(); // 开启session,用于存储登录用户信息 require_once 'C:\xampp\htdocs\google-api-php-client--PHP8.0\vendor\autoload.php'; $CLIENT_ID = 'xxxxx.apps.googleusercontent.com'; // 末尾添加分号 // 从GET请求中获取Google传递的JWT Token if (!isset($_GET['credential'])) { // 无token,跳转回登录页 header("Location: login.php"); exit; } $id_token = $_GET['credential']; $client = new Google_Client(['client_id' => $CLIENT_ID]); $payload = $client->verifyIdToken($id_token); if ($payload) { // 验证通过,获取用户信息 $user_id = $payload['sub']; $user_email = $payload['email']; $user_name = $payload['name']; $user_domain = $payload['hd']; // 企业邮箱域名,对应前端data-hd设置 // 验证企业域名是否匹配(可选,确保只有企业邮箱用户能登录) if ($user_domain !== 'xxx') { // 替换为你的企业域名 header("Location: login.php?error=invalid_domain"); exit; } // 将用户信息存入session,供主页面使用 $_SESSION['logged_in'] = true; $_SESSION['user_name'] = $user_name; $_SESSION['user_email'] = $user_email; // 跳转至主页面 header("Location: main.php"); exit; } else { // 验证失败,跳转回登录页并提示错误 header("Location: login.php?error=invalid_token"); exit; } ?>
4. 前端代码优化建议
- 移除重复的
data-callback属性(ux_mode=redirect模式下,前端回调不会触发) - 统一
data-locale值(当前同时设置了vi和es-419,保持一致) - 移除无效的
redirect_uri属性(Google Sign In中应使用data-login_uri)
内容的提问来源于stack exchange,提问作者Elian Robles
相关产品推荐
相关产品推荐

