我一直在问自己同样的问题,我提出的解决方案与您所解释的非常相似。我正在开发一个 Android 应用程序,它只使用 Parse 作为它的用户和会话部分,其他一切都将是 MySQL、Redis 或我计划在未来包装的任何其他数据源。我已经使用 PHP 和 Slim 框架在 VPS 上开发了我自己的 Rest API。我通过在我自己生成的用户表中添加一个 ApiKey 列来利用 Parse 中的身份验证部分,然后还利用已经为每个用户创建和管理的 SessionToken。当用户对我的 Web 服务进行经过身份验证的调用时,他们会在每个请求标头中提供 api 密钥和会话令牌,并且当我的服务器收到请求时,它会通过 Parse 结束验证来确保 apiKey + sessionToken 对有效。每次用户重新登录时都会重新创建 sessionToken,因此这在一定程度上保证了它的安全。所以目前我正在使用 Parse Android SDK 客户端和 Parse PHP SDK 服务器端。我已经能够创建有关解析的用户、登录用户和列表用户端点。您提到的“成为”能力确实帮助我解决了用户将会话令牌发送到服务器并尝试验证它的问题,因为只有当前用户可以查看他们自己的会话信息。我在 PHP 文档中找不到任何提及它的内容,但显然它是可用的,您只需执行以下操作。如果您有任何想法或意见可以使这变得更好,我愿意接受。
DBHandlerParse 类摘录:
/**
* Validating user api key
* If the api key is there in db, it is a valid key
* @param String $api_key user api key
* @return boolean
*/
public function isValidApiKey($api_key) {
$query = ParseUser::query();
$query->equalTo("apiKey",$api_key);
$results = $query->find();
if(count($results) > 0){
return true;
} else{
return false;
}
}
/**
* Validating user session token
* If the session token matches the api key user, it is a valid token
* @param String $session_token user session token
* @param String $api_key user api key
* @return boolean
*/
public function isValidSessionToken($session_token, $api_key) {
// Using already validated $api_key, obtain corresponding user object
$query = ParseUser::query();
$query->equalTo("apiKey",$api_key);
$results = $query->find();
if(count($results) > 0){
$userObj = $results[0];
} else{
return FALSE;
}
try{
// Become user that has this session token
// Only way to query back the user that they are
// If no user is found with this token, parse error
$thisUser = ParseUser::become($session_token);
$query = ParseSession::query();
$query->equalTo("user", $userObj);
$results = $query->find();
if(count($results) > 0){
return TRUE;
} else{
return FALSE;
}
} catch (Parse\ParseException $error){
return FALSE;
}
}
身份验证中间件:
/**
* Adding Middle Layer to authenticate every request
* Checking if the request has valid api key in the 'Authorization' & 'Token' header
*/
function authenticate(\Slim\Route $route) {
// Getting request headers
$headers = apache_request_headers();
$response = array();
$app = \Slim\Slim::getInstance();
// Verifying Authorization Header
if (isset($headers['Authorization']) && isset($headers['Token'])) {
$db = new DbHandlerParse();
// get the api key
$api_key = $headers['Authorization'];
// get the session token
$session_token = $headers['Token'];
// validating api key
if (!$db->isValidApiKey($api_key)) {
// api key is not present in users table
$response["result"] = "error";
$response["message"] = "Access Denied. Invalid Api key";
echoRespnse(401, $response);
$app->stop();
} else if(!$db->isValidSessionToken($session_token, $api_key)) {
// session token does not match api key or is just invalid
$response["result"] = "error";
$response["message"] = "Access Denied. Invalid Token";
echoRespnse(401, $response);
$app->stop();
} else {
global $user_id;
// get user primary key id
$userID = $db->getUserId($api_key);
if (NULL != $userID)
$user_id = $userID;
}
} else if(!isset($headers['Authorization'])){
// api key is missing in header
$response["result"] = "error";
$response["message"] = "Api key is misssing";
echoRespnse(400, $response);
$app->stop();
} else {
// token is missing in header
$response["result"] = "error";
$response["message"] = "Token is misssing";
echoRespnse(400, $response);
$app->stop();
}
}
示例路线:
/**
* Users List
* url - /list
* method - GET
*/
$app->get('/users/list', 'authenticate', function() use ($app) {
$response = array();
$db = new DbHandlerParse();
$results = $db->getUserList();
$records = array();
//echo "Successfully retrieved " . count($results) . " scores.<br><br>";
// Do something with the returned ParseObject values
for ($i = 0; $i < count($results); $i++) {
$object = $results[$i];
$record = array();
$records[$i]['userId'] = $object->getObjectId();
$records[$i]['firstName'] = $object->get('firstName');
$records[$i]['lastName'] = $object->get('lastName');
$records[$i]['username'] = $object->get('username');
$records[$i]['email'] = $object->get('email');
//echo $object->getObjectId() . ' - ' . $object->get('username') . '<br>';
}
// check for records returned
if ($records) {
$response["result"] = "success";
$response['message'] = count($records)." users found.";
$response['items'] = $records;
} else {
// no records found
$response['result'] = 'success';
$response['message'] = 'No Users Found';
}
echoRespnse(200, $response);
});