我正在尝试创建一个自定义Api,其中包含一个名为callToMethod
的方法。此方法调用另一个称为bypassSugarAuthenticationVariables
的方法,该方法会将3个变量设置为我为其分配的值:
$_REQUEST['platform']
$_GET['oauth_token']
或$_POST['oauth_token']
$_SESSION['authenticated_user_id']
调用此函数后,我使用cURL
在rest
内对应用程序中的另一个API(SugarCRM callToMethod
)进行了RestService
调用,期望这些变量将保持不变。但是,该调用的端点无法识别任何这些变量。
我无法修改RestService
端点,因为它会变得不安全。
我尝试使用CURLOPT_POSTFIELDS
,但是它不起作用,而且我认为无论如何都无法将$_REQUEST['platform']
和$_SESSION['authenticated_user_id']
传递给它。
有没有一种方法可以将这些变量从定制Api发送到rest
端点,而无需修改RestService
?
这是我自定义的Api:
<?php
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
class customPortalApi extends SugarApi
{
protected $store;
public function registerApiRest() //register methods here
{
return array(
'customToken' => array(
'reqType' => 'POST',
'path' => array('customPortalApi', 'customToken'),
'pathVars' => array('', ''),
'method' => 'customToken',
'shortHelp' => 'OAuth2 token requests.',
'longHelp' => 'include/api/help/oauth2_token_post_help.html',
'noLoginRequired' => true,
'keepSession' => true,
'ignoreMetaHash' => true,
'ignoreSystemStatusError' => true,
),
'callToMethod' => array(
'reqType' => 'POST',
'path' => array('customPortalApi', 'callToMethod'),
'pathVars' => array('', ''),
'method' => 'callToMethod',
'shortHelp' => 'Method call request.',
'longHelp' => '',
'noLoginRequired' => true,
'keepSession' => true,
'ignoreMetaHash' => true,
'ignoreSystemStatusError' => true,
)
);
}
public function customToken($api, array $args) //generate custom token if unavailable/expired
{
$module = BeanFactory::getBean($args["module"]);
$module->retrieve_by_string_fields(array(
"email" => $args["email"],
"password_c" => $args["user"]
));
if ($module->id) {
$userData = $this->checkTokenValid("id", $module->id);
if ($userData == false) {
$authData = array(
"token" => $this->genAccessToken(),
"expires_on" => date('Y-m-d', strtotime(date("Y/m/d") . ' + 1 days')),
"module" => $args["module"],
"id" => $module->id,
);
$this->saveToken($authData);
return $authData;
} else {
return $userData;
}
} else {
die("Invalid creds");
// tell the credentials are wrong.
}
}
public function checkTokenValid($field, $id) //series of checks to see if the token exists / is valid
{
$sql = sprintf("SELECT * FROM `custom_oauth` WHERE $field LIKE '%s'", $id);
$result = $GLOBALS['db']->query($sql);
$row = $result->fetch_assoc();
$currDate = date('Y-m-d', strtotime(date("Y/m/d")));
//also check if the token has expired
if ($row['expires_on'] <= $currDate) {
$sql = sprintf("DELETE FROM `custom_oauth` WHERE $field LIKE '%s'", $id);
$result = $GLOBALS['db']->query($sql);
return false;
} elseif (empty($row)) {
return false;
} else {
return $row;
}
}
protected function saveToken(array $arr) //save to custom table
{
$sql = sprintf("INSERT INTO `custom_oauth` (`id`, `module`, `token`, `expires_on`) VALUES ('%s', '%s', '%s', '%s')",
$arr["id"], $arr["module"], $arr["token"], $arr["expires_on"]);
$result = $GLOBALS['db']->query($sql);
}
public function callToMethod($api, array $args)
{
if ($this->checkTokenValid("token", $args['token']) !== false) {
$this->bypassSugarAuthenticationVariables($args['platform'], $args['request_type'], $args['token']);
//here
$recent_url = "http://localhost/SugarPro-Full-8.0.0/rest/v11_1/Leads";
$recent_request = curl_init($recent_url);
curl_setopt($recent_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($recent_request, CURLOPT_HEADER, false);
curl_setopt($recent_request, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($recent_request, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($recent_request, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($recent_request, CURLOPT_HTTPHEADER, array(
"Content-Type: application/json",
"oauth-token: {$args['token']} "
));
//execute request
$recent_response = curl_exec($recent_request);
//decode json
$recent_response_obj = json_decode($recent_response);
//end
}
}
protected function genAccessToken()
{
$tokenLen = 40;
if (file_exists('/dev/urandom')) { // Get 100 bytes of random data
$randomData = file_get_contents('/dev/urandom', false, null, 0, 100) . uniqid(mt_rand(), true);
} else {
$randomData = mt_rand() . mt_rand() . mt_rand() . mt_rand() . microtime(true) . uniqid(mt_rand(), true);
}
return substr(hash('sha512', $randomData), 0, $tokenLen);
}
// pretty functions doing awesome stuff to trick sugar variables
public function initializeSystemUser()
{
$current_user = BeanFactory::retrieveBean('Users');
$GLOBALS['current_user'] = $current_user->getSystemUser();
}
public function setPlatform($platform)
{
$_REQUEST['platform'] = $platform;
}
public function setAuthenticatedUserId()
{
$this->initializeSystemUser();
$_SESSION['authenticated_user_id'] = $GLOBALS['current_user']->id;
}
public function setOauthToken($request_type, $token)
{
if ($request_type == "GET") {
$_GET['oauth_token'] = $token;
} else {
if ($request_type == "POST") {
$_POST['oauth_token'] = $token;
} else {
new SugarApiExceptionInvalidParameter("Invalid Request Type!");
}
}
}
// magic to bundle the awesome functions together
public function bypassSugarAuthenticationVariables($platform, $request_type, $token)
{
$this->setAuthenticatedUserId();
$this->setPlatform($platform);
$this->setOauthToken($request_type, $token);
}
}
SugarCRM RestService
很大,例如,我复制了authenticateUser
和grabToken
方法,以使您了解变量的用法:
AuthenticateUser:
protected function authenticateUser()
{
$valid = false;
die(print_r($_POST));
$token = $this->grabToken();
$platform = !empty($_REQUEST['platform']) ? $_REQUEST['platform'] : 'base';
if ( !empty($token) ) {
try {
$oauthServer = \SugarOAuth2Server::getOAuth2Server($platform);
$oauthServer->verifyAccessToken($token);
if (isset($_SESSION['authenticated_user_id'])) {
$authController = AuthenticationController::getInstance();
// This will return false if anything is wrong with the session
// (mismatched IP, mismatched unique_key, etc)
$valid = $authController->apiSessionAuthenticate();
if ($valid) {
$valid = $this->userAfterAuthenticate($_SESSION['authenticated_user_id'], $oauthServer);
}
if (!$valid) {
// Need to populate the exception here so later code
// has it and can send the correct status back to the client
$e = new SugarApiExceptionInvalidGrant();
}
}
} catch ( OAuth2AuthenticateException $e ) {
// This was failing if users were passing an oauth token up to a public url.
$valid = false;
} catch ( SugarApiException $e ) {
// If we get an exception during this we'll assume authentication failed
$valid = false;
}
}
if (!$valid) {
// If token is invalid, clear the session for bwc
// It looks like a big upload can cause no auth error,
// so we do it here instead of the catch block above
$_SESSION = array();
$exception = (isset($e)) ? $e : false;
return array('isLoggedIn' => false, 'exception' => $exception);
}
return array('isLoggedIn' => true, 'exception' => false);
}
grabToken:
protected function grabToken()
{
// Bug 61887 - initial portal load dies with undefined variable error
// Initialize the return var in case all conditionals fail
$sessionId = '';
$allowGet = (bool) SugarConfig::getInstance()->get('allow_oauth_via_get', false);
if ( isset($_SERVER['HTTP_OAUTH_TOKEN']) ) {
// Passing a session id claiming to be an oauth token
$sessionId = $_SERVER['HTTP_OAUTH_TOKEN'];
} elseif ( isset($_POST['oauth_token']) ) {
$sessionId = $_POST['oauth_token'];
} elseif ($allowGet && !empty($_GET['oauth_token'])) {
$sessionId = $_GET['oauth_token'];
} elseif ( isset($_POST['OAuth-Token']) ) {
$sessionId = $_POST['OAuth-Token'];
} elseif ($allowGet && !empty($_GET['OAuth-Token'])) {
$sessionId = $_GET['OAuth-Token'];
} elseif ( function_exists('apache_request_headers') ) {
// Some PHP implementations don't populate custom headers by default
// So we have to go for a hunt
$headers = apache_request_headers();
foreach ($headers as $key => $value) {
// Check for oAuth 2.0 header
if ($token = $this->getOAuth2AccessToken($key, $value)) {
$sessionId = $token;
break;
}
$check = strtolower($key);
if ( $check == 'oauth_token' || $check == 'oauth-token') {
$sessionId = $value;
break;
}
}
}
return $sessionId;
}