zend-framework - 需要使用 twitter 登录并找回 friend 。我想我把这一切都搞砸了

标签 zend-framework openid twitter-oauth single-sign-on

我正在我的应用程序中集成一个使用 facebook 和 twitter 的标志。我打算稍后在供应商上加入其他标志。实际上,我是根据我在网上找到的一些开放源代码构建它的,但我认为我在这里弄得一团糟。

我的数据库结构如下:

Users
ID|NAME|....|EMAIL|PASSWORD

USER SIGNONS
USER_ID | SIGNIN_TYPE| SIGNIN_ID

当任何人通过使用 facebook 或 twitter 帐户登录来创建帐户时 - 在用户登录表中创建一个条目,指示用户的登录类型为“facebook”或“twitter”。

我使用下面的代码进行身份验证:

public function loginAction() {

    $this->ajaxInit();
    
// get an instace of Zend_Auth
$auth = Zend_Auth::getInstance();
    
    $p = $this->_getAllParams();

    if(isset($p['redirectto'])){
        $this->setRedirect($p['redirectto']);
    }else{
        $redirect = explode('?', $_SERVER['HTTP_REFERER']);
        $this->setRedirect($redirect[0]);
    }
    
// check if a user is already logged
// this checks if he is logged into an open id providor
    /*if ($auth->hasIdentity()) {
    return $this->_redirect('/index/index');
}*/

// if the user is not logged, the do the logging
// $openid_identifier will be set when users 'clicks' on the account provider
$openid_identifier = $this->getRequest()->getParam('openid_identifier', null);

    if($this->getRequest()->getParam('rememberme', null)>0){
        //Zend_Session::rememberMe(60 * 60 * 24 * 30);
    }

// $openid_mode will be set after first query to the openid provider
$openid_mode = $this->getRequest()->getParam('openid_mode', null);

// this one will be set by facebook connect
$code = $this->getRequest()->getParam('code', null);

// while this one will be set by twitter
$oauth_token = $this->getRequest()->getParam('oauth_token', null);


// do the first query to an authentication provider
if ($openid_identifier) {

    if ('https://www.twitter.com' == $openid_identifier) {
        $adapter = $this->_getTwitterAdapter($redirect);
            _log('inside here');
    } else if ('https://www.facebook.com' == $openid_identifier) {
        $adapter = $this->_getFacebookAdapter($redirect);
    } else {
        // for openid
        $adapter = $this->_getOpenIdAdapter($openid_identifier);

        // specify what to grab from the provider and what extension to use
        // for this purpose
        $toFetch = _config('openid', 'tofetch');
        // for google and yahoo use AtributeExchange Extension
        if ('https://www.google.com/accounts/o8/id' == $openid_identifier || 'http://me.yahoo.com/' == $openid_identifier) {
            $ext = $this->_getOpenIdExt('ax', $toFetch);
        } else {
            $ext = $this->_getOpenIdExt('sreg', $toFetch);
        }

        $adapter->setExtensions($ext);
    }

    // here a user is redirect to the provider for loging
        
    $result = $auth->authenticate($adapter);
        
    // the following two lines should never be executed unless the redirection faild.
    //$this->_helper->FlashMessenger('Redirection faild');
        
        if(strstr($redirect, 'import')){
            return $this->_redirect($redirect.'?cmsg=redirection-failure');
        }

    return $this->_redirect('/accounts/sign-in?error=redirection-failure');

}else if ($openid_mode || $code || $oauth_token) {
    // this will be exectued after provider redirected the user back to us
    if ($code) {
        // for facebook
        $adapter = $this->_getFacebookAdapter();
    } else if ($oauth_token) {
        // for twitter
        $adapter = $this->_getTwitterAdapter()->setQueryData($_GET);
    } else {
        // for openid                
        $adapter = $this->_getOpenIdAdapter(null);

        // specify what to grab from the provider and what extension to use
        // for this purpose
        $ext = null;
        
        $toFetch = _config('openid');
        
        // for google and yahoo use AtributeExchange Extension
        if (isset($_GET['openid_ns_ext1']) || isset($_GET['openid_ns_ax'])) {
            $ext = $this->_getOpenIdExt('ax', $toFetch);
        } else if (isset($_GET['openid_ns_sreg'])) {
            $ext = $this->_getOpenIdExt('sreg', $toFetch);
        }

        if ($ext) {
            $ext->parseResponse($_GET);
            $adapter->setExtensions($ext);
        }
    }

    $result = $auth->authenticate($adapter);

    if ($result->isValid()) {
        $toStore = array('identity' => $auth->getIdentity());

            $options = array();

        if ($ext) {
            // for openId
            $toStore['properties'] = $ext->getProperties();
                $options['signin_type'] = 'open_id';
                $toStore['signin_type'] = 'open_id';
                $options['signin_id'] = $auth->getIdentity();
        } else if ($code) {
            // for facebook
            $msgs = $result->getMessages();
            $toStore['properties'] = (array) $msgs['user'];
                $options['signin_type'] = 'facebook';
                $toStore['signin_type'] = 'facebook';
                $options['signin_id'] = $auth->getIdentity();                   
        } else if ($oauth_token) {
            $identity = $result->getIdentity();
            $twitterUserData = (array) $adapter->verifyCredentials();
            $toStore = array('identity' => $identity['user_id']);
            if (isset($twitterUserData['status'])) {
                $twitterUserData['status'] = (array) $twitterUserData['status'];
            }
                _log($twitterUserData);
            $toStore['properties'] = $twitterUserData;
                $options['signin_type'] = 'twitter';
                $toStore['signin_type'] = 'twitter';
                $options['signin_id'] = $identity['user_id'];                   
        }

            $user = _factory('people')->get(false, $options);

            if(count($user)>0){
                $user = array_pop($user);
                $auth->getStorage()->write($user['account_email']);

                return $this->_redirect($this->setRedirect);
                //return $this->_redirect('/accounts/index');
            }else{
                $auth->getStorage()->write($toStore);
                return $this->_redirect('/accounts/welcome');
            }
            

    } else {
        return $this->_redirect('/index/index');
    }
}

我遇到的问题是我正在构建搜索您的 friend 功能。我让它与 facebook 一起工作很容易。但是对于 twitter,我想使用 Zend 框架 Zend_Service_Twitter 代码。但是我发现我需要用户名才能登录并使用访问 token - 我发现此时我并没有完全存储用户名。

目前我的整个程序中只有一个地方进行身份验证,上面发布的代码可通过 www.mysite.com/accounts/login

访问

我的设计有问题,但我不知道是什么。问题是现在我无法登录到 Twitter 帐户来检索任何用户详细信息。但是,我可以通过 Twitter 登录,因为我存储的内容刚好足以验证用户已使用 Twitter 帐户登录,并且相应的用户存在于经过身份验证的帐户中。除此之外,一旦用户登录,我就无法访问用户的推特信息。

我猜 Facebook 让这一切变得简单,因为他们有专门的 API 来处理这个问题。如果我选择添加更多登录,这个问题肯定会在以后给我带来麻烦。

如有任何帮助,我们将不胜感激。上面的代码当然没有规定将帐户关联到已登录的用户。

我应该如何构建我的登录代码和表格。

我在这里使用的是 zend 框架。

最佳答案

据我了解,您的问题是您在使用 Twitter 进行身份验证后没有存储用户名和 access_token。我认为您应该能够获取此信息,然后按如下方式存储它(新位由注释/* 换行 */标记):

   } else if ($oauth_token) {
        $identity = $result->getIdentity();
        $twitterUserData = (array) $adapter->verifyCredentials();

        $toStore = array('identity' => $identity['user_id']);
        if (isset($twitterUserData['status'])) {
            $twitterUserData['status'] = (array) $twitterUserData['status'];
        }
            _log($twitterUserData);
        $toStore['properties'] = $twitterUserData;
        $options['signin_type'] = 'twitter';
        $toStore['signin_type'] = 'twitter';


        /* new line */  
        $accessToken = $adapter->getAccessToken();

        // $accessToken should be an instance of Zend_Oauth_Token_Access
        // and it should contain screen_name, auth_token, etc.
        // to make sure it contains what it should do:
        // var_dump($accessToken); exit;            

        /* new line */ 
        $toStore['access_token'] = $accessToken;

        $options['signin_id'] = $identity['user_id'];                   
    }

因此,假设这里一切顺利,您的 $accessToken 应该与您的身份一起存储。因此,要在其他地方使用它,您可以执行以下操作:

    $auth = Zend_Auth::getInstance();

    if ($auth->hasIdentity()) {
        $identity = $auth->getIdentity();
        $accessToken = $identity['access_token'];

        // Zend_Service_Twitter can accept instance of Zend_Oauth_Token_Access 
        $twitter = new Zend_Service_Twitter(array(               
            'accessToken' => $accessToken
        ));

        try {
             // do whatever twitter operation you want (or is permitted) ,e.g.
             $response   = $twitter->status->update('My Great Tweets'); 

             var_dump($response);

        } catch (Exception $e) {

            // In case something went wrong, e.g. our access token expired or is wrong
            var_dump($e->getMessage());
        }
     }

希望这会有所帮助,或者至少提供一些线索。

关于zend-framework - 需要使用 twitter 登录并找回 friend 。我想我把这一切都搞砸了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6562568/

相关文章:

zend-framework - zend-framework,从另一个 Action 助手中调用 Action 助手

zend-framework - 从 Controller 操作中设置/添加 View

python - 是否可以在开发服务器上测试 Google App Engine OpenID 身份验证?

asp.net-mvc-4 - MVC4 中的 DotNetOpenAuth Twitter API 版本 1.1 调用

php - MVC [Zend 框架] : where to apply filtering and validation

zend-framework - Zend 框架 : Get bootstrap resource from anywhere in application

zend-framework - 将 OpenID 与 Zend Framework 结合使用

php - 使用 OpenID 进行身份验证后在 REST 应用程序中管理 session

delphi - Twitter API 获取提及

android - 更新 Facebook APK 后,FACEBOOK/TWITTER 登录不再适用于 Android 应用程序(登录立即消失!)