如何跨多个AJAX请求维护CakePHP会话?

时间:2013-12-02 08:45:32

标签: ajax facebook session cakephp

坚果壳中的问题

我需要能够在CakePHP中跨多个AJAX请求维护会话。目前,会话在每个AJAX请求中都会丢失。

背景

我正在尝试将Facebook应用程序的服务器端(PHP-SDK)身份验证转换为使用客户端(JS-SDK)身份验证。该应用程序使用CakePHP构建,并使用Auth组件。

我想要实现的用户流程如下:

  1. 用户输入应用
  2. 用户点击“使用Facebook登录”按钮,并通过Facebook身份验证对话框授权该应用。我获取了FB访问令牌,并通过AJAX调用将其传递给服务器。
  3. 使用访问令牌,服务器确定当前用户是新用户还是现有用户,并执行必要的注册和/或登录过程。
  4. 用户可能仍在同一页面上,并可能触发需要用户身份验证的其他AJAX功能(在CakePHP和Facebook上)。
  5. 服务器应该读取先前通过AJAX调用启动的会话,如果用户已通过身份验证,请执行所需的操作。
  6. 我遇到的问题是上述流程的第5步。特别是,$this->Auth->loggedIn()在第二次(和后续)AJAX调用中返回false,并且我收到HTTP 403错误。根据我的观察,似乎没有维护会话,因为$this->Session->id()为每个AJAX调用返回不同的值。

    我在StackOverflow上看了很多类似的问题,但还没找到合适的答案。我看过一些人:

    这是我的会话配置:

    Configure::write('Session', array(
        'defaults' => 'database',
        'checkAgent' => false,
        'ini' => array(
            'session.cookie_secure' => false,
            'session.referer_check' => false,
            'session.cookie_httponly' => false
        )
    ));
    

    我也试过Configure::write('Security.level', 'medium')也无济于事。

    如果有帮助,这是我用于AJAX登录的代码:

    public function ajax_login() {
        $this->autoRender = false;
    
        $data = array();
    
        $accessToken = $this->request->data['access_token'];
    
        $response = null;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_URL, 'https://graph.facebook.com/oauth/access_token?client_id=' . FACEBOOK_SECURITY_APP_ID . '&client_secret=' . FACEBOOK_SECURITY_SECRET . '&grant_type=fb_exchange_token&fb_exchange_token=' . $accessToken);
        parse_str(curl_exec($ch), $response);
        curl_close($ch);
    
        $newAccessToken = $response['access_token'];
    
        FB::setAccessToken($newAccessToken);
    
        try {
            $facebookUser = FB::api('/me', 'GET', array('fields' => 'id,username,first_name,last_name,email'));
    
            //Log in user
            //NOTE:: FB::getUser() returns 0 for some reason
            if ($facebookUser) {
                $isLoggedIn = $this->Auth->loggedIn();
    
                //Log out app user if Facebook IDs do not match
                if ($isLoggedIn) {
                    $appUser = $this->User->find('first', array(
                        'conditions' => array('id' => $this->Auth->user('id')),
                        'recursive' => -1
                    ));
    
                    if ($appUser && $appUser['User']['facebook_id'] != $facebookUser['id']) {
                        $this->Auth->logout();
                    }
                }
    
                //Log in Facebook user
                $user = $this->User->findOrCreate($facebookUser);
    
                if (!$isLoggedIn) {
                    $this->Auth->login($user['User']);
                }
            }
            //Log out app user if Facebook authentication fails
            else if ($this->Auth->loggedIn()) {
                $this->Auth->logout();  
            }
        }
        catch (FacebookApiException $e) {
            $data['error'] = $e->getResult();
        }
    
        $data['status'] = $this->Auth->loggedIn() ? 1 : 0;
    
        echo json_encode($data);
    }
    

    其他要点

    加成

    如果有人能够另外解释为什么上面代码中的FB :: getUser()返回0,虽然FB :: api('/ me')可以工作,但会很棒。

1 个答案:

答案 0 :(得分:0)

我一直在使用Nick的Facebook插件。
当您连接Facebook时,该插件将自动登录用户(如果没有帐户,则创建用户记录)。听起来你想要做的事情已经被插件处理了。

我错过了什么吗?