使用 PHP 从 OAuth REST API 获取 LinkedIn 个人资料

Posted

技术标签:

【中文标题】使用 PHP 从 OAuth REST API 获取 LinkedIn 个人资料【英文标题】:Get LinkedIn profile from OAuth REST API with PHP 【发布时间】:2015-05-12 12:45:35 【问题描述】:

我用过这个网站:http://blog.thewebcafes.com/post/1502524959/php-step-by-step-oauth-for-dummies-based-on

创建以下php页面:

<?php
  if(!isset($_SESSION))session_start();

  define('LINKEDIN_KEY', '**************');
  define('LINKEDIN_SECRET', '****************');

  //Prepare The Links
  $links = array(
    'request_token'=>'https://api.linkedin.com/uas/oauth/requestToken',
    'authorize'=>'https://www.linkedin.com/uas/oauth/authorize',
    'access_token'=>'https://api.linkedin.com/uas/oauth/accessToken'
  );

  //Validate Parameters Passed Back by LinkedIn
  if(isset($_GET['oauth_token']) && isset($_GET['oauth_verifier']) && $_GET['oauth_token']==$_SESSION['linkedin_oauth_token']) 
    //we have user permission, let's get a token
    getAccessToken();
    getProfile();
  else 
    //we don't have an authed user yet, let's ask for permission
    authUser();
  

  function urlencode_oauth($str) 
    return str_replace('+',' ',str_replace('%7E','~',rawurlencode($str)));
  

  function getProfile() 
    global $links;
    //Prepare OAuth Parameters
    $params = array(
      'oauth_consumer_key'=>LINKEDIN_KEY,
      'oauth_nonce'=>sha1(microtime()),
      'oauth_signature_method'=>'HMAC-SHA1',
      'oauth_timestamp'=>time(),
      'oauth_token'=>$_SESSION['linkedin_access_token'],
      'oauth_version'=>'1.0'
    );

    //Prepare The Base String
    // sort parameters according to ascending order of key
    ksort($params);

    // prepare URL-encoded query string
    $q = array();
    foreach ($params as $key=>$value) 
      $q[] = urlencode_oauth($key).'='.urlencode_oauth($value);
    
    $q = implode('&',$q);

    // generate the base string for signature
    $parts = array(
      'GET',
      urlencode_oauth('https://api.linkedin.com/v1/people/~:(id,num-connections,picture-url)?format=json'),
      urlencode_oauth($q)
    );
    $base_string = implode('&',$parts);

    //Get The Signature
    $key = urlencode_oauth(LINKEDIN_SECRET) . '&' . urlencode_oauth($_SESSION['linkedin_access_token_secret']);
    $signature = base64_encode(hash_hmac('sha1',$base_string,$key,true));

    //Put the Signature into Parameters and Prepare Authorization Header
    $params['oauth_signature'] = $signature;
    $str = array();
    foreach ($params as $key=>$value) 
      $str[] = $key . '="'.urlencode_oauth($value).'"';
    
    $str = implode(', ',$str);
    $headers = array(
      'GET /v1/people/~ HTTP/1.1',
      'Host: api.linkedin.com',
      'Authorization: OAuth '.$str,
      'Connection: Keep-Alive',
      'Content-Type: application/json',
      'x-li-format: json'
    );

    //Send GET Request To LinkedIn
    $fp = fsockopen("ssl://api.linkedin.com",443,$errno,$errstr,30);
    if(!$fp)  echo 'Unable to connect to LinkedIn'; exit(); 
    $out = implode("\r\n",$headers)."\r\n\r\n".$xml . "\r\n\r\n";
    fputs($fp,$out);

    // getting LinkedIn server response
    $res = '';
    while (!feof($fp)) $res .= fgets($fp,4096);
    fclose($fp);
    echo 'RESPONSE: ' . $res;
    //Make sure the GET is successful
    $parts = explode("\n\n",str_replace("\r","",$res));
    $headers = explode("\n",$parts[0]);
    if ($headers[0] != 'HTTP/1.1 201 Created')  echo 'Failed'; 
  

  function getAccessToken() 
    global $links;
    //Prepare OAuth Parameters
    $params = array(
      'oauth_consumer_key'=>LINKEDIN_KEY,
      'oauth_nonce'=>sha1(microtime()),
      'oauth_signature_method'=>'HMAC-SHA1',
      'oauth_timestamp'=>time(),
      'oauth_token'=>$_GET['oauth_token'],
      'oauth_verifier'=>$_GET['oauth_verifier'],
      'oauth_version'=>'1.0'
    );

    //Prepare The Base String
    // sort parameters according to ascending order of key
    ksort($params);

    // prepare URL-encoded query string
    $q = array();
    foreach ($params as $key=>$value) 
      $q[] = urlencode_oauth($key).'='.urlencode_oauth($value);
    
    $q = implode('&',$q);

    // generate the base string for signature
    $parts = array(
      'POST',
      urlencode_oauth($links['access_token']),
      urlencode_oauth($q)
    );
    $base_string = implode('&',$parts);

    //Get The Signature
    $key = urlencode_oauth(LINKEDIN_SECRET) . '&' . urlencode_oauth($_SESSION['linkedin_oauth_token_secret']);
    $signature = base64_encode(hash_hmac('sha1',$base_string,$key,true));

    //Put the Signature into Parameters and Prepare Authorization Header
    $params['oauth_signature'] = $signature;
    $str = array();
    foreach ($params as $key=>$value) 
      $str[] = $key . '="'.urlencode_oauth($value).'"';
    
    $str = implode(', ',$str);
    $headers = array(
      'POST /uas/oauth/accessToken HTTP/1.1',
      'Host: api.linkedin.com',
      'Authorization: OAuth '.$str,
      'Content-Type: text/xml;charset=UTF-8',
      'Content-Length: 0',
      'Connection: close'
    );

    //Send POST Request To LinkedIn
    $fp = fsockopen("ssl://api.linkedin.com",443,$errno,$errstr,30);
    if (!$fp)  echo 'Unable to connect to LinkedIn'; exit(); 
    $out = implode("\r\n",$headers) . "\r\n\r\n";
    fputs($fp,$out);

    // getting LinkedIn server response
    $res = '';
    while (!feof($fp)) $res .= fgets($fp,4096);
    fclose($fp);

    //Parse the Response to Get The Access Token and Secret
    $parts = explode("\n\n",str_replace("\r",'',$res));
    $res_headers = explode("\n",$parts[0]);
    if ($res_headers[0] != 'HTTP/1.1 200 OK') 
      echo 'Error getting access token and secret.'; exit();
    
    parse_str($parts[1],$data);
    if (empty($data['oauth_token'])) 
      echo 'Failed to get LinkedIn access token.'; exit();
    

    //Save the Request Token and Secret
    $_SESSION['linkedin_access_token'] = $data['oauth_token'];
    $_SESSION['linkedin_access_token_secret'] = $data['oauth_token_secret'];

    // unset the Request Token (not needed anymore)
    unset($_SESSION['linkedin_oauth_token']);
    unset($_SESSION['linkedin_oauth_token_secret']);
  

  function authUser() 
    global $links;
    //Prepare OAuth Parameters
    $params = array(
      'oauth_callback'=>"https://sxsw.ampthealth.com/linkedin_callback.php",
      'oauth_consumer_key'=>LINKEDIN_KEY,
      'oauth_nonce'=>sha1(microtime()),
      'oauth_signature_method'=>'HMAC-SHA1',
      'oauth_timestamp'=>time(),
      'oauth_version'=>'1.0'
    );

    //Prepare The Base String
    // sort parameters according to ascending order of key
    ksort($params);

    // prepare URL-encoded query string
    $q = array();
    foreach ($params as $key=>$value) 
      $q[] = urlencode_oauth($key).'='.urlencode_oauth($value);
    
    $q = implode('&',$q);

    // generate the base string for signature
    $parts = array(
      'POST',
      urlencode_oauth($links['request_token']),
      urlencode_oauth($q)
    );
    $base_string = implode('&',$parts);

    //Get The Signature
    $key = urlencode_oauth(LINKEDIN_SECRET) . '&';
    $signature = base64_encode(hash_hmac('sha1',$base_string,$key,true));

    //Put the Signature into Parameters and Prepare Authorization Header
    $params['oauth_signature'] = $signature;
    $str = array();
    foreach ($params as $key=>$value) 
      $str[] = $key . '="'.urlencode_oauth($value).'"';
    
    $str = implode(', ',$str);
    $headers = array(
      'POST /uas/oauth/requestToken HTTP/1.1',
      'Host: api.linkedin.com',
      'Authorization: OAuth '.$str,
      'Content-Type: text/xml;charset=UTF-8',
      'Content-Length: 0',
      'Connection: close'
    );

    //Send POST Request To LinkedIn
    $fp = fsockopen("ssl://api.linkedin.com",443,$errno,$errstr,30);
    if (!$fp)  echo 'Unable to connect to LinkedIn'; exit(); 
    $out = implode("\r\n",$headers) . "\r\n\r\n";
    fputs($fp,$out);

    // getting LinkedIn server response
    $res = '';
    while (!feof($fp)) $res .= fgets($fp,4096);
    fclose($fp);

    //Parse the Response to Get OAuth Token and Secret
    $parts = explode("\n\n",str_replace("\r",'',$res));
    $res_headers = explode("\n",$parts[0]);
    if ($res_headers[0] != 'HTTP/1.1 200 OK') 
      echo 'Error getting OAuth token and secret.'; exit();
    
    parse_str($parts[1],$data);
    if (empty($data['oauth_token'])) 
      echo 'Failed to get LinkedIn request token.'; exit();
    

    //Save the Request Token and Secret
    $_SESSION['linkedin_oauth_token'] = $data['oauth_token'];
    $_SESSION['linkedin_oauth_token_secret'] = $data['oauth_token_secret'];

    //Redirect your user to LinkedIn with the request token
    header('Location: '.$links['authorize'].'?oauth_token='.urlencode($data['oauth_token']));
    exit();
  
?>

我能够让用户授权并请求访问令牌,但是在获取基本配置文件时,我收到一个错误:401 Unauthorized Server。我的 getProfile 函数一定有问题,但我对我缺少的东西有点迷茫。

【问题讨论】:

【参考方案1】:

您必须按照linkedin 文档here 中的步骤操作。

特别要阅读申请被批准这一点。

【讨论】:

我熟悉此文档,并认为自己处于第 4 步而不是第 2 步。很可能是我的代码存在问题,而且我与 LinkedIn 的连接也存在问题。

以上是关于使用 PHP 从 OAuth REST API 获取 LinkedIn 个人资料的主要内容,如果未能解决你的问题,请参考以下文章

OAuth、PHP、Rest API 和 curl 给出 400 Bad Request

Magento 使用 OAuth 通过 REST API 到 NodeJS

REST API 的安全认证,从 OAuth 2.0 到 JWT 令牌

需要使用 Keycloak 和 oAuth2 保护普通 Spring REST API 的示例

需要使用Keycloack和oAuth2保护普通Spring REST API的示例

Salesforce OAuth 与 REST API 使用 Javascript