通过php curl模拟Discourse SSO登录

问题描述 投票:0回答:2

我正在将 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"

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

任何人都可以看出其中的问题或找出逻辑中的任何缺陷吗?

single-sign-on symfony-1.4 discourse
2个回答
0
投票

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

为了避免弄乱标头并避免 iframe 等出现问题,我做了这样的操作,使其仅使用 curl 来检索包含有效负载数据的初始 url。

一旦我抓住了这些,我就会根据给定的有效负载处理并构造新的请求,然后将它们传递给正在发出登录请求(即来自浏览器)的隐藏框架,然后JavaScript将接管以删除该隐藏框架并加载新的一个正在加载用户已经登录的主讨论页面。

希望它对将来的人有所帮助。


0
投票

我正在使用这种话语方法之一。我也遇到同样的错误。

“账号登录超时,请尝试重新登录”

我按照这个方法但仍然显示错误。创建有效负载后,我将重定向它但显示错误。您能指导我如何解决这个问题吗?

© www.soinside.com 2019 - 2024. All rights reserved.