PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/addons/plugin/Login/lib/baidu/Baidu.php

https://github.com/cxc222/weibo
PHP | 341 lines | 168 code | 31 blank | 142 comment | 33 complexity | 72b6aeb4dc15ff0b66d484b69cd8d6d7 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /***************************************************************************
  3. *
  4. * Copyright (c) 2011 Baidu.com, Inc. All Rights Reserved
  5. *
  6. **************************************************************************/
  7. require_once( 'BaiduStore.php');
  8. require_once( 'BaiduOAuth2.php');
  9. require_once( 'BaiduApiClient.php');
  10. require_once( 'BaiduUtils.php');
  11. /**
  12. *
  13. * @package Baidu
  14. * @author zhujianting(zhujianting@baidu.com)
  15. * @version v2.0.0
  16. */
  17. class BaiduAPI
  18. {
  19. /**
  20. * The client_id of the app or access_key of the developer.
  21. * @var string
  22. */
  23. protected $clientId;
  24. /**
  25. * The client_secret of the app or secret_key of the developer.
  26. * @var string
  27. */
  28. protected $clientSecret;
  29. /**
  30. * Redirect uri of the app, where we will redirect to after user authorization.
  31. * @var string
  32. */
  33. protected $redirectUri;
  34. /**
  35. * Storage for the user session related datas, like state, authorization code,
  36. * access token and so on.
  37. *
  38. * @var BaiduStore
  39. */
  40. protected $store = null;
  41. /**
  42. * @var string
  43. */
  44. protected $state = null;
  45. /**
  46. * User session info.
  47. * @var array
  48. */
  49. protected $session = null;
  50. /**
  51. * @var BaiduOAuth2
  52. */
  53. protected $oauth2 = null;
  54. /**
  55. * Constructor
  56. *
  57. * @param string $clientId The client_id of the app or access_key of the developer.
  58. * @param string $clientSecret The client_secret of the app or secret_key of the developer.
  59. * @param string $redirectUri Redirect uri of the app.
  60. * @param BaiduStore $store Storage for the user session related datas.
  61. */
  62. public function __construct($clientId, $clientSecret, $redirectUri, $store = null)
  63. {
  64. $this->clientId = $clientId;
  65. $this->clientSecret = $clientSecret;
  66. $this->redirectUri = $redirectUri;
  67. $this->setStore($store ? $store : new BaiduCookieStore($clientId));
  68. }
  69. /**
  70. * Get an instance of BaiduOAuth2 class.
  71. *
  72. * @return BaiduOAuth2
  73. */
  74. public function getBaiduOAuth2Service()
  75. {
  76. if (!$this->oauth2) {
  77. $this->oauth2 = new BaiduOAuth2($this->clientId, $this->clientSecret);
  78. $this->oauth2->setRedirectUri($this->redirectUri);
  79. }
  80. return $this->oauth2;
  81. }
  82. /**
  83. * Get an instance of BaiduApiClient class.
  84. *
  85. * @param string $accessToken Access token for api calls.
  86. * @return BaiduApiClient
  87. */
  88. public function getBaiduApiClientService()
  89. {
  90. return new BaiduApiClient($this->clientId, $this->getAccessToken());
  91. }
  92. /**
  93. * Get access token for openapi calls.
  94. *
  95. * @return string|false Returns access token if user has authorized the app, or false if not.
  96. */
  97. public function getAccessToken()
  98. {
  99. $session = $this->getSession();
  100. if (isset($session['access_token'])) {
  101. return $session['access_token'];
  102. } else {
  103. return false;
  104. }
  105. }
  106. /**
  107. * Get refresh token.
  108. *
  109. * @return string|false Returns refresh token if app has, or false if not.
  110. */
  111. public function getRefreshToken()
  112. {
  113. $session = $this->getSession();
  114. if (isset($session['refresh_token'])) {
  115. return $session['refresh_token'];
  116. } else {
  117. return false;
  118. }
  119. }
  120. /**
  121. * Get currently logged in user's uid.
  122. *
  123. * @return uint|false Return uid of the loggedin user, or return
  124. * false if user isn't loggedin.
  125. */
  126. public function getLoggedInUser()
  127. {
  128. // Get user from cached data or from access token
  129. $user = $this->getUser();
  130. // If there's bd_sig & bd_user parameter in query parameters,
  131. // it must be an inside web app(app on baidu) loading request,
  132. // then we must check whether the uid passed from baidu is the
  133. // same as we get from persistent data or from access token,
  134. // if it's not, we should clear all the persistent data and to
  135. // get an access token again.
  136. if (isset($_REQUEST['bd_sig']) && isset($_REQUEST['bd_user'])) {
  137. $params = array('bd_user' => $_REQUEST['bd_user']);
  138. $sig = BaiduUtils::generateSign($params, $this->clientSecret, 'bd_sig');
  139. if ($sig != $_REQUEST['bd_sig'] || $user['uid'] != $_REQUEST['bd_user']) {
  140. $this->store->remove('session');
  141. return false;
  142. }
  143. }
  144. return $user;
  145. }
  146. /**
  147. * Get a Login URL for use with redirects. By default, full page redirect is
  148. * assumed. If you are using the generated URL with a window.open() call in
  149. * JavaScript, you can pass in display=popup as part of the $params.
  150. *
  151. * @param string $scope blank space separated list of requested extended perms
  152. * @param string $display Authorization page style, 'page', 'popup', 'touch' or 'mobile'
  153. * @return string the URL for the login flow
  154. */
  155. public function getLoginUrl($scope = '', $display = 'page')
  156. {
  157. $oauth2 = $this->getBaiduOAuth2Service();
  158. return $oauth2->getAuthorizeUrl('code', $scope, $this->state, $display);
  159. }
  160. /**
  161. * Get the Logout URL suitable for use with redirects.
  162. *
  163. * @param string $next Url to go to after a successful logout.
  164. *
  165. * @return string
  166. */
  167. public function getLogoutUrl($next)
  168. {
  169. $oauth2 = $this->getBaiduOAuth2Service();
  170. return $oauth2->getLogoutUrl($this->getAccessToken(), $next);
  171. }
  172. /**
  173. * Get user session info.
  174. *
  175. * @return array
  176. */
  177. public function getSession()
  178. {
  179. if ($this->session === null) {
  180. $this->session = $this->doGetSession();
  181. }
  182. return $this->session;
  183. }
  184. /**
  185. * Set user session.
  186. *
  187. * @param array $session User session info.
  188. * @return Baidu
  189. */
  190. public function setSession($session)
  191. {
  192. $this->session = $session;
  193. if ($session) {
  194. $this->store->set('session', $session);
  195. } else {
  196. $this->store->remove('session');
  197. }
  198. return $this;
  199. }
  200. /**
  201. * Get current user's uid and uname.
  202. *
  203. * @return array|false array('uid' => xx, 'uname' => xx)
  204. */
  205. protected function getUser()
  206. {
  207. $session = $this->getSession();
  208. if (is_array($session) && isset($session['uid']) && isset($session['uname'])) {
  209. return array('uid' => $session['uid'], 'uname' => $session['uname']);
  210. } else {
  211. return false;
  212. }
  213. }
  214. /**
  215. * Set the session data storage instance.
  216. *
  217. * @param BaiduStore $store
  218. * @return Baidu
  219. */
  220. protected function setStore($store)
  221. {
  222. $this->store = $store;
  223. if ($this->store) {
  224. $state = $this->store->get('state');
  225. if (!empty($state)) {
  226. $this->state = $state;
  227. }
  228. //as the storage engine is changed, we need to get the session again.
  229. $this->session = null;
  230. $this->getSession();
  231. $this->establishCSRFTokenState();
  232. }
  233. return $this;
  234. }
  235. /**
  236. * Get session info from Baidu server or from the store in app server side.
  237. *
  238. * @return array|false
  239. */
  240. protected function doGetSession()
  241. {
  242. // get authorization code from query parameters
  243. $code = $this->getCode();
  244. // check whether it is a CSRF attack request
  245. if ($code && $code != $this->store->get('code')) {
  246. $oauth2 = $this->getBaiduOAuth2Service();
  247. $session = $oauth2->getAccessTokenByAuthorizationCode($code);
  248. if ($session) {
  249. $this->store->set('code', $code);
  250. $this->setSession($session);
  251. $apiClient = new BaiduApiClient($this->clientId, $session['access_token']);
  252. $user = $apiClient->api('passport/users/getLoggedInUser');
  253. if ($user) {
  254. $session = array_merge($session, $user);
  255. $this->setSession($session);
  256. }
  257. return $session;
  258. }
  259. // code was bogus, so everything based on it should be invalidated.
  260. $this->store->removeAll();
  261. return false;
  262. }
  263. // as a fallback, just return whatever is in the storage
  264. $session = $this->store->get('session');
  265. $this->setSession($session);
  266. if ($session && !isset($session['uid'])) {
  267. $apiClient = new BaiduApiClient($this->clientId, $session['access_token']);
  268. $user = $apiClient->api('passport/users/getLoggedInUser');
  269. if ($user) {
  270. $session = array_merge($session, $user);
  271. $this->setSession($session);
  272. }
  273. }
  274. return $session;
  275. }
  276. /**
  277. * Get the authorization code from the query parameters, if it exists,
  278. * otherwise return false to signal no authorization code was discoverable.
  279. *
  280. * @return mixed Returns the authorization code, or false if the authorization
  281. * code could not be determined.
  282. */
  283. protected function getCode()
  284. {
  285. if (isset($_GET['code'])) {
  286. if ($this->state && $this->state === $_GET['state']) {
  287. // CSRF state has done its job, so clear it
  288. $this->state = null;
  289. $this->store->remove('state');
  290. return $_GET['code'];
  291. } else {
  292. BaiduUtils::errorLog('CSRF state token does not match one provided.');
  293. return false;
  294. }
  295. }
  296. return false;
  297. }
  298. /**
  299. * Lays down a CSRF state token for this process.
  300. *
  301. * @return void
  302. */
  303. protected function establishCSRFTokenState()
  304. {
  305. if ($this->state === null) {
  306. $this->state = md5(uniqid(mt_rand(), true));
  307. $this->store->set('state', $this->state);
  308. }
  309. }
  310. }