Created
January 10, 2013 07:05
-
-
Save enyachoke/4500113 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Baofeng\Ucenter; | |
class OAuth | |
{ | |
const REQUEST_TOKEN_TTL = 1800; | |
const TOKEN_TTL = -1; // unlimited | |
const TIMESTAMP_TTL = 1800; | |
const NONCE_TTL = 1800; | |
public function __construct(\Silex\Application $app) { | |
$this->app = $app; | |
} | |
/** | |
* Consumer Provider | |
* @param $provider | |
* @return int | |
*/ | |
public function lookupConsumer($provider) { | |
$consumer = $this->getConsumer($provider->consumer_key); | |
if(!$consumer) { | |
return \OAUTH_CONSUMER_KEY_UNKNOWN; | |
} else if($consumer['key_status'] != 0) { // 0 is active, 1 is throttled, 2 is blacklisted | |
return \OAUTH_CONSUMER_KEY_REFUSED; | |
} | |
$provider->consumer_secret = $consumer['shared_secret']; | |
return \OAUTH_OK; | |
} | |
/** | |
* Validate timestamp and nonce | |
* @param $provider | |
* @return int | |
*/ | |
public function timestampNonceChecker($provider) { | |
$timestamp = $provider->timestamp; | |
$nonce = $provider->nonce; | |
// TODO check timestamp and nonce | |
return \OAUTH_OK; | |
} | |
/** | |
* Generate Tokens | |
* @static | |
* @return array | |
*/ | |
public static function generateToken() { | |
$secret = \OAuthProvider::generateToken(32); | |
$hash = sha1($secret); | |
return array(substr($hash,0,25), substr($hash,25,15)); | |
} | |
/** | |
* Validate Request Token | |
* @param $provider | |
* @return int | |
*/ | |
public function requestTokenHandler($provider) { | |
$token = $this->getRequestToken($provider->token); | |
if (!$token) { | |
return \OAUTH_TOKEN_REJECTED; | |
} else { | |
$provider->token_secret = $token['token_secret']; | |
return \OAUTH_OK; | |
} | |
} | |
public function saveRequestToken($token, $secret, $consumer_key, $callback, $verifier, $user_id) { | |
$token_array = array( | |
'token_key'=>$token, | |
'token_secret'=>$secret, | |
'consumer_key'=>$consumer_key, | |
'callback'=>$callback, | |
'verifier'=>$verifier, | |
'user_id'=>$user_id, | |
); | |
$this->app['cache']->set('RTOKEN:'.$token, json_encode($token_array), self::REQUEST_TOKEN_TTL); | |
} | |
public function getRequestToken($token) { | |
if (empty($token)) return null; | |
$json = $this->app['cache']->get('RTOKEN:'.$token); | |
return json_decode($json, true); | |
} | |
public function deleteRequestToken($token) { | |
return $this->app['cache']->purge('RTOKEN:'.$token); | |
} | |
/** | |
* Validate access token | |
* @param $provider | |
* @return int | |
*/ | |
public function accessTokenHandler($provider) { | |
$token = $this->getAccessToken($provider->token); | |
if (!$token || $token['token_status'] != 0) { | |
return \OAUTH_TOKEN_REJECTED; | |
} else if (self::TOKEN_TTL > 0 && ($token['create_time'] + self::TOKEN_TTL) < time()) { | |
return \OAUTH_TOKEN_EXPIRED; | |
} else { | |
$provider->token_secret = $token['token_secret']; | |
return \OAUTH_OK; | |
} | |
} | |
public function saveAccessToken($token, $secret, $consumer_key, $user_id, $app_id) { | |
$db = $this->app['dbs']['db']; | |
$token_id = $db->fetchColumn("SELECT id FROM oauth_token WHERE user_id=? AND consumer_key=?", array($user_id, $consumer_key), 0); | |
$row = array( | |
'token_key'=>$token, | |
'token_secret'=>$secret, | |
'consumer_key'=>$consumer_key, | |
'user_id'=>$user_id, | |
'resource_id'=>$app_id, | |
'token_status'=>0, | |
'create_time'=>time(), | |
); | |
if ($token_id) { | |
$this->app['dbs']['db']->update('oauth_token', $row, array('id'=>$token_id)); | |
} else { | |
$this->app['dbs']['db']->insert('oauth_token', $row); | |
} | |
} | |
public function getAccessToken($token) { | |
if (empty($token)) return null; | |
$db = $this->app['dbs']['db']; | |
$token = $db->fetchAssoc("SELECT * FROM oauth_token WHERE token_key=?", array($token)); | |
return $token; | |
} | |
private function getConsumer($ck) { | |
$db = $this->app['dbs']['db']; | |
$consumer = $db->fetchAssoc("SELECT * FROM oauth_consumer WHERE consumer_key=?", array($ck)); | |
return $consumer; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Symfony\Component\HttpKernel\Exception\HttpException; | |
use Baofeng\Ucenter\Utils; | |
use Baofeng\Ucenter\Model\User; | |
use Baofeng\Common\BaofengHttpException; | |
use Symfony\Component\HttpFoundation\ParameterBag; | |
use Symfony\Component\HttpFoundation\Cookie; | |
use Symfony\Component\HttpFoundation\Response; | |
$oauth_api = new \Silex\ControllerCollection(); | |
/** | |
* 获取临时request_token | |
*/ | |
$oauth_api->match('/v1/request_token', function(\Silex\Application $app) { | |
try { | |
$bfoa = new \Baofeng\Ucenter\OAuth($app); | |
$provider = new \OAuthProvider(array()); | |
$provider->isRequestTokenEndpoint (true); | |
$provider->consumerHandler(array($bfoa,'lookupConsumer')); | |
$provider->timestampNonceHandler(array($bfoa,'timestampNonceChecker')); | |
$provider->checkOAuthRequest($app['base_url'] . 'oauth/v1/request_token'); | |
$app['monolog']->addDebug(var_export($provider,true)); | |
} catch (\OAuthException $ex) { | |
echo \OAuthProvider::reportProblem($ex); | |
return; | |
} | |
$token = \Baofeng\Ucenter\OAuth::generateToken(); | |
$bfoa->saveRequestToken($token[0], $token[1], $provider->consumer_key, $provider->callback, '', 0); | |
$result = array( | |
'oauth_token' => $token[0], | |
'oauth_token_secret' => $token[1], | |
'oauth_callback_confirmed' => true | |
); | |
return http_build_query($result); | |
}); | |
/** | |
* 获取授权token | |
*/ | |
$oauth_api->match('/v1/access_token', function(\Silex\Application $app) { | |
try { | |
$bfoa = new \Baofeng\Ucenter\OAuth($app); | |
$provider = new \OAuthProvider(array()); | |
$provider->isRequestTokenEndpoint (false); | |
$provider->consumerHandler(array($bfoa,'lookupConsumer')); | |
$provider->timestampNonceHandler(array($bfoa,'timestampNonceChecker')); | |
$provider->tokenHandler(array($bfoa,'requestTokenHandler')); | |
$provider->checkOAuthRequest(); | |
$app['monolog']->addDebug(var_export($provider,true)); | |
} catch (\OAuthException $ex) { | |
echo \OAuthProvider::reportProblem($ex); | |
return; | |
} | |
$token = $bfoa->getRequestToken($provider->token); | |
if ($token['verifier'] != $provider->verifier) { | |
throw HttpException('Invalid verifier', 402); | |
} | |
$bfoa->deleteRequestToken($token['token_key']); | |
$atoken = \Baofeng\Ucenter\OAuth::generateToken(); | |
$bfoa->saveAccessToken($atoken[0], $atoken[1], $provider->consumer_key, $token['user_id'], ''); | |
$result = array( | |
'oauth_token' => $atoken[0], | |
'oauth_token_secret' => $atoken[1], | |
); | |
return http_build_query($result); | |
}); | |
/** | |
* 登陆授权页 | |
*/ | |
$oauth_api->get('/v1/authorize', function(\Silex\Application $app) { | |
$app['session']->start(); | |
// 记录授权请求发起页面 | |
if (isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], '.baofeng.com') === false) { | |
$app['session']->set('referrer_url', $_SERVER['HTTP_REFERER']); | |
} | |
$req_token = $app['request']->get('oauth_token'); | |
if (!$req_token) { | |
$req_token = $app['session']->get('token'); | |
} | |
$bfoa = new \Baofeng\Ucenter\OAuth($app); | |
$user_model = new User($app); | |
$user_model->checkAutoLogin(); | |
if ($token = $bfoa->getRequestToken($req_token)) { | |
$app['session']->set('token', $req_token); | |
$data = array('request_token'=>$req_token); | |
if ($app['session']->get('user_id')) { //已登录 | |
$data['user_id'] = $app['session']->get('user_id'); | |
$data['user'] = $user_model->getUserById($data['user_id']); | |
} | |
if ($app['session']->get('fail_login', 0) >= 3) { | |
$data['show_vcode'] = true; | |
} | |
return $app['twig']->render('login.html.twig', $data); | |
} else { | |
throw new BaofengHttpException(402, "授权请求已失效,请重试"); | |
} | |
}); | |
$oauth_api->post('/v1/authorize', function(\Silex\Application $app) { | |
$app['session']->start(); | |
$bfoa = new \Baofeng\Ucenter\OAuth($app); | |
$req_token = $app['session']->get('token', ''); | |
if ($req_token == '') { | |
throw new BaofengHttpException(402, '授权请求已过期,请重试'); | |
} | |
if ($app['session']->get('user_id', 0) == 0) { | |
$username = $app['request']->get('username'); | |
$password = $app['request']->get('password'); | |
$stay_login = $app['request']->get('stay_login', false); | |
$user_model = new User($app); | |
$uid = $user_model->getUserIdByName($username); | |
$user = $user_model->getUserById($uid); | |
if (intval($app['session']->get('fail_login', 0)) >= 3) { | |
if (strtolower($app['request']->get('verify_code', '')) != strtolower($app['session']->get('verify_code', '-1'))) { | |
$app['session']->setFlash('error', '验证码错误'); | |
$app['session']->setFlash('username', $username); | |
$app['session']->setFlash('stay_login', $stay_login); | |
return $app->redirect('/oauth/v1/authorize'); | |
} | |
} | |
if (!$user || strtolower($user['password']) != Utils::password($password)) { | |
$app['session']->setFlash('error', '用户名或密码错误'); | |
$app['session']->setFlash('username', $username); | |
$app['session']->setFlash('stay_login', $stay_login); | |
// increase fail login counter | |
$fail_login = intval($app['session']->get('fail_login', 0)); | |
$app['session']->set('fail_login', $fail_login + 1); | |
return $app->redirect('/oauth/v1/authorize'); | |
} | |
$app['session']->set('user_id', $uid); | |
$app['session']->remove('fail_login'); | |
if ($stay_login) { | |
$cookie = new Cookie('bf_sso_token', $user_model->generateUserToken($user['username'], $user['password']), Utils::getDaysAfter(30), '/', '.baofeng.com'); | |
} | |
} | |
$token = $bfoa->getRequestToken($req_token); | |
$verify_code = $bfoa->generateToken(); | |
$bfoa->saveRequestToken($req_token, $token['token_secret'], $token['consumer_key'], $token['callback'], $verify_code[0], $app['session']->get('user_id')); | |
$verify = array('oauth_token'=>$req_token, 'oauth_verifier'=>$verify_code[0]); | |
if (strpos($token['callback'], '?') === false) { | |
$url = $token['callback'] . '?' . http_build_query($verify); | |
} else { | |
$url = $token['callback'] . '&' . http_build_query($verify); | |
} | |
$app['session']->remove('token'); | |
$response = $app->redirect($url); | |
if (isset($cookie)) { | |
$response->headers->setCookie($cookie); | |
} | |
if (isset($cookie2)) { | |
$response->headers->setCookie($cookie2); | |
} | |
return $response; | |
}); | |
/** | |
* 获取用户信息 | |
*/ | |
$oauth_api->get('/v1/userinfo', function(\Silex\Application $app) { | |
try { | |
$bfoa = new \Baofeng\Ucenter\OAuth($app); | |
$provider = new \OAuthProvider(array()); | |
$provider->isRequestTokenEndpoint (false); | |
$provider->consumerHandler(array($bfoa,'lookupConsumer')); | |
$provider->timestampNonceHandler(array($bfoa,'timestampNonceChecker')); | |
$provider->tokenHandler(array($bfoa,'accessTokenHandler')); | |
$provider->checkOAuthRequest(); | |
} catch (\OAuthException $ex) { | |
echo \OAuthProvider::reportProblem($ex); | |
return; | |
} | |
// OAuth check passed | |
$user_model = new \Baofeng\Ucenter\Model\User($app); | |
$token = $bfoa->getAccessToken($provider->token); | |
$user = $user_model->getUserById($token['user_id']); | |
if (!$user) { | |
throw new HttpException('User not found', 404); | |
} | |
$result = array('user_id'=>$user['user_id'], 'username'=>$user['username']); | |
return json_encode($result); | |
}); | |
return $oauth_api; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment