Skip to content

Instantly share code, notes, and snippets.

@enyachoke
Created January 10, 2013 07:05
Show Gist options
  • Save enyachoke/4500113 to your computer and use it in GitHub Desktop.
Save enyachoke/4500113 to your computer and use it in GitHub Desktop.
<?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;
}
}
<?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