鲲圭发现
将Linkedin登录集成到你的独立站
1. 创建应用
登录到Linkedin开发者账号中心:https://www.linkedin.com/developers/login,选择My Apps -> Create app,
创建好应用后,在应用详情页“Auth"部分,可查看Client ID和Client Secret,稍后我们需要用到。
接着我们还需要配置“Redirect URLs”部分,这个地址便是用户授权通过后返回到你的网站处理授权码的接收点,需要注意URL地址有以下规则和限制:
- URL地址必须包含完整路径,比如
https://example.com/auth/callback
, 不能是这种相对路径/auth/callback
; - URL中的参数将被忽略, 比如
https://example.com/?id=1
,Linkedin在回调该网址时不会携带id=1参数; - URL不允许包含 “#”,比如
https://example.com/auth/callback#linkedin
2. 发起授权请求
我们创建一个LinkedIn类,添加一个getAuthorizeURL()方法,用于生成授权请求链接:
<?php
class LinkedIn {
/** @var 申请的应用Client ID */
private $key;
/** @var 申请的应用Client Secret */
private $secret;
/** @var 授权回调地址,需在你的应用设置Redirect URLs中有匹配记录 */
private $redirect;
/** @var 授权范围,需与你的应用设置Permissions 部分一致*/
private $scope = 'r_emailaddress r_liteprofile w_member_social';
public function __construct($key, $secret, $redirect) {
$this->key = $key;
$this->secret = $secret;
$this->redirect = $redirect;
}
public function getAuthorizeURL() {
$params = [
'response_type' => 'code',
'client_id' => $this->key,
'redirect_uri' => $this->redirect,
'state' => uniqid('', true),
'scope' => $this->scope
];
session_start();
$_SESSION['linkedin_state'] = $params['state'];
return 'https://www.linkedin.com/oauth/v2/authorization?'.http_build_query($params);
}
}
用户点击生成的链接后,将会跳转到Linkedin授权页面:
3. 换取 access_token
access_token是经用户授权后可获取用户基本信息的钥匙,我们在上一步授权完成后会拿到授权码,通过授权码可以换取access_token。在LinkedIn类中增加getAccessToken()方法:
public function getAccessToken() {
session_start();
if(!(isset($_REQUEST['code']) && isset($_REQUEST['state']) && $_SESSION['linkedin_state'] == $_REQUEST['state'])) {
throw new Exception('Invalid access');
}
$params = [
'grant_type' => 'authorization_code',
'code' => $_REQUEST['code'],
'redirect_uri' => $this->redirect,
'client_id' => $this->key,
'client_secret' => $this->secret,
];
$url = 'https://www.linkedin.com/oauth/v2/accessToken';
$response = file_get_contents($url, false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query($params)
]
]));
if(!$response) throw new Exception('HTTP request failed.');
$token = json_decode($response);
return $token->access_token;
}
4. 获取用户基本信息
用户基本信息的获取貌似在微软收购LinkedIn后发生了些许变化,以前的获取方式变得不可用了:
public function getUserInfo($token) {
$params = [
'oauth2_access_token' => $token,
'format' => 'json'
];
$url = 'https://api.linkedin.com/v2/people/~'.'?'.http_build_query($params);
$response = file_get_contents($url, false, stream_context_create([
'http' => [
'method' => 'GET'
]
]));
$data = json_decode($response);
if(!$data) throw new Exception($data);
return $data;
}
翻阅最新文档发现,Linkedin的文档地址都迁移到到微软服务器,真是变成一家人了啊?,重新调整后的getUserInfo()方法:
public function getUserInfo($token) {
$url = 'https://api.linkedin.com/v2/me';
$response = file_get_contents($url, false, stream_context_create([
'http' => [
'method' => 'GET',
'header' => 'Authorization: Bearer '.$token
]
]));
$data = json_decode($response);
if(!$data) throw new Exception($data);
return $data;
}
返回的用户信息数据结构如下:
{
"firstName":{
"localized":{
"en_US":"Bob"
},
"preferredLocale":{
"country":"US",
"language":"en"
}
},
"localizedFirstName": "Bob",
"headline":{
"localized":{
"en_US":"API Enthusiast at LinkedIn"
},
"preferredLocale":{
"country":"US",
"language":"en"
}
},
"localizedHeadline": "API Enthusiast at LinkedIn",
"vanityName": "bsmith",
"id":"yrZCpj2Z12",
"lastName":{
"localized":{
"en_US":"Smith"
},
"preferredLocale":{
"country":"US",
"language":"en"
}
},
"localizedLastName": "Smith",
"profilePicture": {
"displayImage": "urn:li:digitalmediaAsset:C4D00AAAAbBCDEFGhiJ"
}
}
我们通过其中的属性 id 来识别该用户的唯一性,通过 vantyName 来获得用户昵称,profilePicture.displayImage 则是用户头像。基本上我们获取了这些信息对本文第三方登录集来说就足够了。