通过php curl模拟话语SSO登录

时间:2015-09-03 14:47:29

标签: single-sign-on symfony-1.4 discourse

我正在将Discourse集成到我们的平台(使用iframe),我正在努力了解我做错了什么,并且无法让SSO对我的用户进行身份验证。

我正在研究symfony 1.4,我的动作既包含显示页面的逻辑(包含iframe),也包含记录用户的逻辑。

public function executeViewDiscussionForum(sfWebRequest $request){        

    $requestIsInternal  = $request->getParameter('isInternal');

    if($requestIsInternal==='1'){
        //====Discourse will redirect here again with the payload parameters
        $response = DiscourseAuthDriver::makeCurlRequest('http://****.****.com:8080');
    }

    $url = parse_url($response['Location']);
    $cookie = $response['Set-Cookie'];
    parse_str($url['query'], $params);
    $sso = $params['sso'];
    $signature = $params['sig'];

    // load the payload passed in by Discourse
    $payload = $sso;

    $ssoHelper = new SSOHelper();
    // this should be the same in your code and in your Discourse settings:
    $secret = '****';
    $ssoHelper->setSecret( $secret );



    // validate the payload
    if (!($ssoHelper->validatePayload($payload,$signature))) {
        // invaild, deny
        $this->redirect404();
    }

    $nonce = $ssoHelper->getNonce($payload);

    // Insert your user authentication code here ...

    // Required and must be unique to your application
    $userId = $this->currentUser->id;

    // Required and must be consistent with your application
    $userEmail = $this->currentUser->getEmailAddress();

    // Optional - if you don't set these, Discourse will generate suggestions
    // based on the email address

    $extraParameters = array(
        'username' => $this->currentUser->getUsername(),
        'name'     => $this->currentUser->getFullname()
    );


    // build query string and redirect back to the Discourse site
    $query = $ssoHelper->getSignInString($nonce, $userId, $userEmail, $extraParameters);
    DiscourseAuthDriver::makeCurlRequest('http://*****.***.com:8080/session/sso_login?' . $query, $cookie); 
}

我正在使用的SSOHelper类是找到的here

DiscourseAuthDriver :: makeCurlRequest如下:

public static function makeCurlRequest($url, $cookie=null){
        $ch = curl_init($url);
        if($cookie){
            curl_setopt($ch, CURLOPT_HTTPHEADER, array("Set-Cookie: ".$cookie));
            curl_setopt($ch, CURLOPT_NOBODY, 1);
        }
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0"); // Necessary. The server checks for a valid User-Agent.        
        $response = curl_exec($ch);
        $header = $response;
        $header = self::get_headers_from_curl_response($header);

        curl_close($ch);
        return $header[1];
    }

如果我没有启用SSO,我可以看到主要话语页面在我的iframe中加载得很好。

上面的逻辑是,通过使用curl,我可以基本上模拟登录过程,然后在iframe中提供登录页面,但即使我手动导航到URL中的登录,也似乎不会将其剪切掉散列参数和所有我得到以下错误:

"Account login timed out, please try logging in again"

我已经检查了其他可能的答案以及我的设置,并且我没有设置批准选项,所以我认为这可能是由于在请求登录时未传递会话信息,但即使添加后它似乎也没有工作

任何人都可以看到这个有什么问题或者找出逻辑中的任何缺陷吗?

1 个答案:

答案 0 :(得分:0)

我不知道如何,但由于某种原因,请求网址今天正常工作,它确实对我的用户进行了身份验证。

为了避免混淆标题并遇到iframe等问题,我做了它,以便它只使用curl来检索包含有效负载数据的初始URL。

一旦我抓住这些,我处理并根据给定的有效负载构建新请求,然后将em传递给一个隐藏的框架,该框架正在发出登录请求(即从浏览器)javascript然后接管删除这个隐藏的框架和加载一个正在加载主要话语页面的新用户已经登录。

希望将来帮助某人。