移动应用程序:PHP 中忽略 cookie?

问题描述 投票:0回答:1
我的场景如下:我的移动应用程序向外部网站发送授权请求,以接收授权代码,该授权代码被发送到重定向 URI 以交换“访问令牌”。我想将此令牌存储在 firebase 实时数据库中,但使用通过我的应用程序发出该请求的用户的唯一用户 ID。原因是,可能有多个用户向网站发出该请求,当然我需要将它们分开,包括令牌的安全存储。没有 uuid,一切正常,令牌将保存到 firebase。

我现在开始更新我的代码。使用OAuth 2.0,但是,状态管理未在第3方网站上设置,因此我不能只传递编码的uuid,因为服务器仅返回授权代码。所以我编写了一个脚本(storeUuid.php),它接收编码的uuid,对其进行解码,将其保存在定时cookie中,以便同一域(auth.example.com)上的其他脚本可以访问该cookie并使用它。服务器上有第二个脚本 (redirect.php),该脚本由对第 3 方网站的授权请求触发,接收授权代码并应该将其交换为访问令牌。但是,在此之前,它应访问 cookie 并提取 uuid。但是,它总是抛出 {error:UUID not found in the cookie}。

<?php // storeUuid.php session_start(); // Function to return JSON response function jsonResponse($data) { header('Content-Type: application/json'); echo json_encode($data); } // Function to log errors function logError($message) { error_log("Error: $message"); } session_set_cookie_params([ 'lifetime' => 3600, 'path' => '/', 'domain' => 'auth.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'None' ]); // Function to store UUID in session and cookie function storeUUID($encodedUUID) { $decodedUUID = base64_decode($encodedUUID); if ($decodedUUID) { $_SESSION['userUid'] = $decodedUUID; setcookie("decodedUUID", $decodedUUID, time()+3600, "/", "auth.example.com"); jsonResponse(["success" => "UUID stored in session and cookie.", "decodedUUID" => htmlspecialchars($decodedUUID), "sessionId" => session_id(), "cookie" => ($_COOKIE)]); } else { logError("No UUID provided or decoding failed."); jsonResponse(["error" => "No UUID provided or decoding failed.", "sessionId" => session_id()]); } } // Check if the request method is POST if ($_SERVER['REQUEST_METHOD'] === 'POST') { $data = json_decode(file_get_contents('php://input'), true); $encodedUUID = isset($data['encodedUserUid']) ? $data['encodedUserUid'] : null; if ($encodedUUID) { storeUUID($encodedUUID); } else { logError("No encoded UUID provided in POST request."); jsonResponse(["error" => "No encoded UUID provided in POST request.", "sessionId" => session_id()]); } } else { logError("Invalid request method."); jsonResponse(["error" => "Invalid request method.", "sessionId" => session_id()]); } ?>
<?php
// redirect.php
session_start();
require __DIR__.'/vendor/autoload.php';

use Kreait\Firebase\Factory;
use Kreait\Firebase\Exception\FirebaseException;

$serviceAccountPath = __DIR__.'/1234ABCD.json';
$databaseUrl = 'https://fundraiser-application-example.com';

function jsonResponse($data) {
    header('Content-Type: application/json');
    echo json_encode($data);
}

// Function to log errors
function logError($message) {
    error_log("Error: $message");
}

// Retrieve the decoded UUID from the cookie
if (isset($_COOKIE['decodedUUID'])) {
    $decodedUUID = $_COOKIE['decodedUUID'];
} else {
    logError("UUID not found in the cookie");
    jsonResponse(["error" => "UUID not found in the cookie"]);
    exit;
}

print_r($_COOKIE); 

if (!isset($_SESSION['userUid'])) {
    logError("User UID not found in session");
    jsonResponse(["error" => "User UID not found in session"]);
    exit;
}

try {
    $firebase = (new Factory)
        ->withServiceAccount($serviceAccountPath)
        ->withDatabaseUri($databaseUrl)
        ->createDatabase();
} catch (FirebaseException $e) {
    logError("Firebase Error: " . $e->getMessage());
    jsonResponse(["error" => "Firebase Error: " . $e->getMessage()]);
    exit;
} catch (Exception $e) {
    logError("General Error: " . $e->getMessage());
    jsonResponse(["error" => "General Error: " . $e->getMessage()]);
    exit;
}

$clientID = 'MY_CLIENT_ID';
$clientSecret = 'MY_SECRET_Key';
$tokenURL = 'https://auth.3rdparty.com/oauth/token';

if (isset($_GET['code'])) {
    $authorizationCode = $_GET['code'];
    $postData = http_build_query([
        'grant_type' => 'authorization_code',
        'client_id' => $clientID,
        'client_secret' => $clientSecret,
        'code' => $authorizationCode,
        'redirect_uri' => 'https://auth.example.com/redirect'
    ]);

    $context = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
            'content' => $postData
        ]
    ]);

    $response = file_get_contents($tokenURL, false, $context);

    if ($response === FALSE) {
        logError("Error in token request");
        jsonResponse(["error" => "Error in token request"]);
        exit;
    }

    $responseData = json_decode($response, true);

    if (isset($responseData['access_token'])) {
        $accessToken = $responseData['access_token'];
        $userUid = $_SESSION['userUid'];

        $firebase->getReference('users/' . $userUid . '/example/access_token/')->set($accessToken);
        jsonResponse(["success" => "Access Token stored successfully for user", "userUid" => htmlspecialchars($userUid)]);
        
        $_SESSION = array();
        session_destroy();
    } else {
        logError("Access token not found in response or user UID not available in session");
        jsonResponse(["error" => "Access token not found in response or user UID not available in session", "response" => $responseData]);
    }
} else {
    logError("Authorization code not found");
    jsonResponse(["error" => "Authorization code not found"]);
}
?>
这是两个文件。如前所述,据我所知,我从 storeUuid.php 获得的响应日志显示一切正常:

LOG Initiating OAuth process... LOG Encoded user UID: ABCD1234 LOG Response from storeUuid.php: Array ( [decodedUUID] => BFM6OIHuCBe56s08cgcnmiEotff1 [PHPSESSID] => lgh2gphfbbolcimv0abkkmrere ) {"success":"UUID stored in session and cookie.","decodedUUID":"5678DCBA","sessionId":"my_session_id","cookie":{"decodedUUID":"5678DCBA","PHPSESSID":"my_session_id"}} LOG Authorization URL: https://auth.3rdparty.com/oauth/authorize?response_type=code&client_id=(MY_CLIENT_ID)&redirect_uri=https://auth.example.com/redirect&scope=read LOG OAuth URL opened successfully.
但是我正在测试应用程序的设备上的浏览器抛出该错误,它无法在 cookie 或会话中找到 UUID。

我添加了 print_r($_COOKIE);在redirect.php中查看cookie内容是什么,但没有显示任何内容。

任何建议都会非常有帮助!

php google-cloud-platform oauth-2.0 apache2
1个回答
0
投票
我通过使用自定义会话处理程序找到了解决方案。

class CustomSessionHandler implements SessionHandlerInterface { private $redis; public function open($savePath, $sessionName) { // Initialize the Redis connection $this->redis = new Redis(); $this->redis->connect('127.0.0.1', 6379); return true; } public function close() { // Close the Redis connection $this->redis->close(); return true; } public function write($id, $data) { $this->setSessionData($id, $data); return true; } public function read($id) { $data = $this->redis->hGet("session:$id", "data"); return $data === false ? '' : $data; } public function destroy($id) { // Attempt to delete the session data from Redis $result = $this->redis->del("session:$id"); if ($result === false) { // Log the error or handle it accordingly error_log("Failed to delete session data for ID: $id"); return false; } return true; } public function gc($maxlifetime) { // Redis automatically handles expiration, so no need for manual garbage collection return 0; } public function setSessionData($id, $data) { // Set session data in your custom way $this->redis->hSet("session:$id", "data", $data); $this->redis->expire("session:$id", 600); // data expires after 10 minutes } public function getSessionData($id) { // Retrieve session data from Redis based on the session ID return $this->redis->hGet("session:$id", "data"); } } // Register the custom session handler and start session $handler = new CustomSessionHandler(); session_set_save_handler($handler, true); session_start();
    
© www.soinside.com 2019 - 2024. All rights reserved.