mirror of
https://github.com/DzzXH/DzzOffice.git
synced 2026-01-22 07:05:18 +08:00
341 lines
8.7 KiB
PHP
341 lines
8.7 KiB
PHP
<?php
|
|
/***************************************************************************
|
|
*
|
|
* Copyright (c) 2011 Baidu.com, Inc. All Rights Reserved
|
|
*
|
|
**************************************************************************/
|
|
|
|
require_once( 'BaiduStore.php');
|
|
require_once( 'BaiduOAuth2.php');
|
|
require_once( 'BaiduApiClient.php');
|
|
require_once( 'BaiduUtils.php');
|
|
|
|
/**
|
|
*
|
|
* @package Baidu
|
|
* @author zhujianting(zhujianting@baidu.com)
|
|
* @version v2.0.0
|
|
*/
|
|
class Baidu
|
|
{
|
|
/**
|
|
* The client_id of the app or access_key of the developer.
|
|
* @var string
|
|
*/
|
|
protected $clientId;
|
|
|
|
/**
|
|
* The client_secret of the app or secret_key of the developer.
|
|
* @var string
|
|
*/
|
|
protected $clientSecret;
|
|
|
|
/**
|
|
* Redirect uri of the app, where we will redirect to after user authorization.
|
|
* @var string
|
|
*/
|
|
protected $redirectUri;
|
|
|
|
/**
|
|
* Storage for the user session related datas, like state, authorization code,
|
|
* access token and so on.
|
|
*
|
|
* @var BaiduStore
|
|
*/
|
|
protected $store = null;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $state = null;
|
|
|
|
/**
|
|
* User session info.
|
|
* @var array
|
|
*/
|
|
protected $session = null;
|
|
|
|
/**
|
|
* @var BaiduOAuth2
|
|
*/
|
|
protected $oauth2 = null;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $clientId The client_id of the app or access_key of the developer.
|
|
* @param string $clientSecret The client_secret of the app or secret_key of the developer.
|
|
* @param string $redirectUri Redirect uri of the app.
|
|
* @param BaiduStore $store Storage for the user session related datas.
|
|
*/
|
|
public function __construct($clientId, $clientSecret, $redirectUri, $store = null)
|
|
{
|
|
$this->clientId = $clientId;
|
|
$this->clientSecret = $clientSecret;
|
|
$this->redirectUri = $redirectUri;
|
|
$this->setStore($store ? $store : new BaiduCookieStore($clientId));
|
|
}
|
|
|
|
/**
|
|
* Get an instance of BaiduOAuth2 class.
|
|
*
|
|
* @return BaiduOAuth2
|
|
*/
|
|
public function getBaiduOAuth2Service()
|
|
{
|
|
if (!$this->oauth2) {
|
|
$this->oauth2 = new BaiduOAuth2($this->clientId, $this->clientSecret);
|
|
$this->oauth2->setRedirectUri($this->redirectUri);
|
|
}
|
|
return $this->oauth2;
|
|
}
|
|
|
|
/**
|
|
* Get an instance of BaiduApiClient class.
|
|
*
|
|
* @param string $accessToken Access token for api calls.
|
|
* @return BaiduApiClient
|
|
*/
|
|
public function getBaiduApiClientService()
|
|
{
|
|
return new BaiduApiClient($this->clientId, $this->getAccessToken());
|
|
}
|
|
|
|
/**
|
|
* Get access token for openapi calls.
|
|
*
|
|
* @return string|false Returns access token if user has authorized the app, or false if not.
|
|
*/
|
|
public function getAccessToken()
|
|
{
|
|
$session = $this->getSession();
|
|
if (isset($session['access_token'])) {
|
|
return $session['access_token'];
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get refresh token.
|
|
*
|
|
* @return string|false Returns refresh token if app has, or false if not.
|
|
*/
|
|
public function getRefreshToken()
|
|
{
|
|
$session = $this->getSession();
|
|
if (isset($session['refresh_token'])) {
|
|
return $session['refresh_token'];
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get currently logged in user's uid.
|
|
*
|
|
* @return uint|false Return uid of the loggedin user, or return
|
|
* false if user isn't loggedin.
|
|
*/
|
|
public function getLoggedInUser()
|
|
{
|
|
// Get user from cached data or from access token
|
|
$user = $this->getUser();
|
|
|
|
// If there's bd_sig & bd_user parameter in query parameters,
|
|
// it must be an inside web app(app on baidu) loading request,
|
|
// then we must check whether the uid passed from baidu is the
|
|
// same as we get from persistent data or from access token,
|
|
// if it's not, we should clear all the persistent data and to
|
|
// get an access token again.
|
|
if (isset($_REQUEST['bd_sig']) && isset($_REQUEST['bd_user'])) {
|
|
$params = array('bd_user' => $_REQUEST['bd_user']);
|
|
$sig = BaiduUtils::generateSign($params, $this->clientSecret, 'bd_sig');
|
|
if ($sig != $_REQUEST['bd_sig'] || $user['uid'] != $_REQUEST['bd_user']) {
|
|
$this->store->remove('session');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return $user;
|
|
}
|
|
|
|
/**
|
|
* Get a Login URL for use with redirects. By default, full page redirect is
|
|
* assumed. If you are using the generated URL with a window.open() call in
|
|
* JavaScript, you can pass in display=popup as part of the $params.
|
|
*
|
|
* @param string $scope blank space separated list of requested extended perms
|
|
* @param string $display Authorization page style, 'page', 'popup', 'touch' or 'mobile'
|
|
* @return string the URL for the login flow
|
|
*/
|
|
public function getLoginUrl($scope = '', $display = 'page')
|
|
{
|
|
$oauth2 = $this->getBaiduOAuth2Service();
|
|
return $oauth2->getAuthorizeUrl('code', $scope, $this->state, $display);
|
|
}
|
|
|
|
/**
|
|
* Get the Logout URL suitable for use with redirects.
|
|
*
|
|
* @param string $next Url to go to after a successful logout.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getLogoutUrl($next)
|
|
{
|
|
$oauth2 = $this->getBaiduOAuth2Service();
|
|
return $oauth2->getLogoutUrl($this->getAccessToken(), $next);
|
|
}
|
|
|
|
/**
|
|
* Get user session info.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getSession()
|
|
{
|
|
if ($this->session === null) {
|
|
$this->session = $this->doGetSession();
|
|
}
|
|
|
|
return $this->session;
|
|
}
|
|
|
|
/**
|
|
* Set user session.
|
|
*
|
|
* @param array $session User session info.
|
|
* @return Baidu
|
|
*/
|
|
public function setSession($session)
|
|
{
|
|
$this->session = $session;
|
|
if ($session) {
|
|
$this->store->set('session', $session);
|
|
} else {
|
|
$this->store->remove('session');
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get current user's uid and uname.
|
|
*
|
|
* @return array|false array('uid' => xx, 'uname' => xx)
|
|
*/
|
|
protected function getUser()
|
|
{
|
|
$session = $this->getSession();
|
|
if (is_array($session) && isset($session['uid']) && isset($session['uname'])) {
|
|
return array('uid' => $session['uid'], 'uname' => $session['uname']);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the session data storage instance.
|
|
*
|
|
* @param BaiduStore $store
|
|
* @return Baidu
|
|
*/
|
|
protected function setStore($store)
|
|
{
|
|
$this->store = $store;
|
|
if ($this->store) {
|
|
$state = $this->store->get('state');
|
|
if (!empty($state)) {
|
|
$this->state = $state;
|
|
}
|
|
//as the storage engine is changed, we need to get the session again.
|
|
$this->session = null;
|
|
$this->getSession();
|
|
$this->establishCSRFTokenState();
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get session info from Baidu server or from the store in app server side.
|
|
*
|
|
* @return array|false
|
|
*/
|
|
protected function doGetSession()
|
|
{
|
|
// get authorization code from query parameters
|
|
$code = $this->getCode();
|
|
// check whether it is a CSRF attack request
|
|
if ($code && $code != $this->store->get('code')) {
|
|
$oauth2 = $this->getBaiduOAuth2Service();
|
|
$session = $oauth2->getAccessTokenByAuthorizationCode($code);
|
|
if ($session) {
|
|
$this->store->set('code', $code);
|
|
$this->setSession($session);
|
|
$apiClient = new BaiduApiClient($this->clientId, $session['access_token']);
|
|
$user = $apiClient->api('passport/users/getLoggedInUser');
|
|
if ($user) {
|
|
$session = array_merge($session, $user);
|
|
$this->setSession($session);
|
|
}
|
|
return $session;
|
|
}
|
|
|
|
// code was bogus, so everything based on it should be invalidated.
|
|
$this->store->removeAll();
|
|
return false;
|
|
}
|
|
|
|
// as a fallback, just return whatever is in the storage
|
|
$session = $this->store->get('session');
|
|
$this->setSession($session);
|
|
if ($session && !isset($session['uid'])) {
|
|
$apiClient = new BaiduApiClient($this->clientId, $session['access_token']);
|
|
$user = $apiClient->api('passport/users/getLoggedInUser');
|
|
if ($user) {
|
|
$session = array_merge($session, $user);
|
|
$this->setSession($session);
|
|
}
|
|
}
|
|
|
|
return $session;
|
|
}
|
|
|
|
/**
|
|
* Get the authorization code from the query parameters, if it exists,
|
|
* otherwise return false to signal no authorization code was discoverable.
|
|
*
|
|
* @return mixed Returns the authorization code, or false if the authorization
|
|
* code could not be determined.
|
|
*/
|
|
protected function getCode()
|
|
{
|
|
if (isset($_GET['code'])) {
|
|
if ($this->state && $this->state === $_GET['state']) {
|
|
// CSRF state has done its job, so clear it
|
|
$this->state = null;
|
|
$this->store->remove('state');
|
|
return $_GET['code'];
|
|
} else {
|
|
BaiduUtils::errorLog('CSRF state token does not match one provided.');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Lays down a CSRF state token for this process.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function establishCSRFTokenState()
|
|
{
|
|
if ($this->state === null) {
|
|
$this->state = md5(uniqid(mt_rand(), true));
|
|
$this->store->set('state', $this->state);
|
|
}
|
|
}
|
|
} |