Desde hace un tiempo he tenido que ir desarrollando algún webservice para unas apps de smartphone y como corrian prisa, para salir del paso los hice un poco a mi manera, pero me gustaria saber que forma usais para desarrollar webservices.
El punto de entrada siempre lo hago asi:
index.php
<?php
if (session_id() == '' ) {
session_start();
$firstConn = true;
}
error_reporting(E_ALL);
/**
* @author: grodriguez
* @version: 2018.02.20
*/
// LOAD CONFIG FILES
require_once("config/general.config.php");
// LOAD CLASS
require_once("class/Logger.class.php");
require_once("class/ADirectory.class.php");
// LOAD CONTROLLERS
require_once("controllers/Base.controller.php");
require_once("controllers/Logged.controller.php");
require_once("controllers/Users.controller.php");
// DEFINE MODULES
const MODULE_USERS = "users";
if ( isset($firstConn) && $firstConn === true ) {
Logger::write("CTRL INDEX > New connection");
}
if ( isset($_POST["module"]) === false || trim($_POST["module"]) == "" ) {
Logger::write("CTRL INDEX > ERROR: No se ha indicado el modulo");
$resp = array();
$resp["code"] = "-1";
$resp["result"] = "KO";
$resp["message"] = "No se ha indicado el módulo --> module ";
echo json_encode($resp);
exit;
}
$module = trim($_POST["module"]);
switch ($module) {
case MODULE_USERS:
$controller = new UsersController();
$controller->direcciona();
break;
default:
$resp = array();
$resp["code"] = "-1";
$resp["result"] = "KO";
$resp["message"] = "Modulo indicado no es un modulo válido (module==".$module.")";
echo json_encode($resp);
break;
}
Tengo un BaseController del que heredaran otros tipos de controller (LoginController, LoggedController)
En aplicaciones donde es el usuario desde la app quien pone su login password (su password puede cambiar, su token se genera en el momento de login) hago uso de LoginController y una vez tiene su token puede hacer llamadas a otros controladores / metodos del webservice. Los metodos que necesitan de estar validado para hacer peticiones , heredan de LoggedController (el cual en su constructor comprueba en la base de datos si ese token es valido).
En caso de ser valido pasara a ejecutarse el direcciona()
<?php
class UsersController extends LoggedController{
const USER_ADD = "create-user";
const USER_LOGIN = "check-login";
const USER_AVAILABLE = "login-available";
const USER_UPDPASSWORD = "update-password";
const USER_MOVEDN = "movedn";
public function __construct() {
parent::__construct();
}
public function direcciona() {
if (!array_key_exists("action", $_POST)) { $action = ""; }
else { $action = trim($_POST['action']); }
echo $action;
Logger::write("CTRL USERS > direcciona > action == ".$action);
switch ( $action ) {
case self::USER_LOGIN:
$this->check_credentials();
break;
case self::USER_AVAILABLE:
$this->check_login_available();
break;
case self::USER_ADD:
$this->create_new_user();
break;
case self::USER_UPDPASSWORD:
$this->update_user_password();
break;
case self::USER_MOVEDN:
$this->move_user();
break;
default:
Logger::write("CTRL USERS > direcciona > Invalid action! == ".$action);
echo json_encode(self::generateErrorWithCode(3));
break;
}
}
protected function check_login_available() {
Logger::write("CTRL USERS > check_login_available");
$bRequiredParametersOK = true;
$failedFields = array();
if (!array_key_exists("login", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "login"; }
if ( $bRequiredParametersOK === false ) {
$resp = $this->generateErrorWithCode(4);
$resp["fields_required"] = array();
$resp["fields_required"][] = "login";
$resp["fields_required"][] = "source_dn";
$resp["fields_required"][] = "target_dn";
$resp["fields_failed"] = $failedFields;
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > check_login_available > ERROR: < ".$json." >");
return;
}
$adirectory = new ADirectory(MSAD_HOST,MSAD_USER,MSAD_PASS,MSAD_BASE,MSAD_DOMAIN);
if ( $adirectory->connect() === false ) {
$adirectory->close();
$json = json_encode($this->generateErrorWithCode(5));
Logger::write("CTRL USERS > move_user > ERROR: < ".$json." >");
echo $json;
return;
}
$login = trim($_POST['login']);
$resultAD = $adirectory->isLoginAvailable($login);
switch ($resultAD) {
case ADirectory::RV_OK;
$resp = $this->generateResponse();
break;
default:
$resp = $this->generateErrorWithCode(7);
break;
}
$resp["adirectory"]["code"] = "".$resultAD;
$resp["adirectory"]["message"] = $adirectory->translateWsCodeToString($resultAD);
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > check_login_available > RESP: < ".$json." >");
$adirectory->close();
}
protected function move_user() {
Logger::write("CTRL USERS > move_user");
$bRequiredParametersOK = true;
$failedFields = array();
if (!array_key_exists("login", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "login"; }
if (!array_key_exists("source_dn", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "source_dn"; }
if (!array_key_exists("target_dn", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "target_dn"; }
if ( $bRequiredParametersOK === false ) {
$resp = $this->generateErrorWithCode(4);
$resp["fields_required"] = array();
$resp["fields_required"][] = "login";
$resp["fields_required"][] = "source_dn";
$resp["fields_required"][] = "target_dn";
$resp["fields_failed"] = $failedFields;
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > move_user > ERROR: < ".$json." >");
return;
}
$adirectory = new ADirectory(MSAD_HOST,MSAD_USER,MSAD_PASS,MSAD_BASE,MSAD_DOMAIN);
if ( $adirectory->connect() === false ) {
$adirectory->close();
$json = json_encode($this->generateErrorWithCode(5));
Logger::write("CTRL USERS > move_user > ERROR: < ".$json." >");
echo $json;
return;
}
$login = trim($_POST["login"]);
$source_dn = trim($_POST["source_dn"]);
$target_dn = trim($_POST["target_dn"]);
$resultAD = $adirectory->moveUser($login,$source_dn,$target_dn);
switch ($resultAD) {
case ADirectory::RV_OK;
$resp = $this->generateResponse();
break;
default:
$resp = $this->generateErrorWithCode(7);
break;
}
$resp["adirectory"]["code"] = "".$resultAD;
$resp["adirectory"]["message"] = $adirectory->translateWsCodeToString($resultAD);
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > move_user > RESP: < ".$json." >");
$adirectory->close();
}
protected function update_user_password() {
Logger::write("CTRL USERS > update_user_password");
$bRequiredParametersOK = true;
$failedFields = array();
if (!array_key_exists("login", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "login"; }
if (!array_key_exists("passw", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "passw"; }
if ( $bRequiredParametersOK === false ) {
$resp = $this->generateErrorWithCode(4);
$resp["fields_required"] = array();
$resp["fields_required"][] = "login";
$resp["fields_required"][] = "passw";
$resp["fields_failed"] = $failedFields;
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > update_user_password > ERROR: ".$json);
return;
}
$adirectory = new ADirectory(MSAD_HOST,MSAD_USER,MSAD_PASS,MSAD_BASE,MSAD_DOMAIN);
if ( $adirectory->connect() === false ) {
$adirectory->close();
$json = json_encode($this->generateErrorWithCode(5));
echo $json;
Logger::write("CTRL USERS > update_user_password > ERROR: < ".$json." >");
return;
}
$login = trim($_POST["login"]);
$passw = trim($_POST["passw"]);
$resultAD = $adirectory->updatePassword($login,$passw);
switch ($resultAD) {
case ADirectory::RV_OK;
$resp = $this->generateResponse();
break;
default:
$resp = $this->generateErrorWithCode(7);
break;
}
$resp["adirectory"]["code"] = "".$resultAD;
$resp["adirectory"]["message"] = $adirectory->translateWsCodeToString($resultAD);
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > update_user_password > RESP: < ".$json." >");
$adirectory->close();
}
protected function check_credentials() {
Logger::write("CTRL USERS > check_credentials");
$bRequiredParametersOK = true;
$failedFields = array();
if (!array_key_exists("login", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "login"; }
if (!array_key_exists("passw", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "passw"; }
if ( $bRequiredParametersOK === false ) {
$resp = $this->generateErrorWithCode(4);
$resp["fields_required"] = array();
$resp["fields_required"][] = "login";
$resp["fields_required"][] = "passw";
$resp["fields_failed"] = $failedFields;
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > check_credentials > ERROR: < ".$json." >");
return;
}
$adirectory = new ADirectory(MSAD_HOST,MSAD_USER,MSAD_PASS,MSAD_BASE,MSAD_DOMAIN);
if ( $adirectory->connect() === false ) {
$adirectory->close();
$json = json_encode($this->generateErrorWithCode(5));
echo $json;
Logger::write("CTRL USERS > check_credentials > ERROR: < ".$json." >");
return;
}
$login = trim($_POST["login"]);
$passw = trim($_POST["passw"]);
$resultAD = $adirectory->checkCredentials($login,$passw);
switch ($resultAD) {
case ADirectory::RV_OK;
$resp = $this->generateResponse();
break;
default:
$resp = $this->generateErrorWithCode(2);
break;
}
$resp["adirectory"]["code"] = "".$resultAD;
$resp["adirectory"]["message"] = $adirectory->translateWsCodeToString($resultAD);
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > check_credentials > RESP: < ".$json." >");
$adirectory->close();
}
protected function create_new_user() {
Logger::write("CTRL USERS > create_new_user");
$bRequiredParametersOK = true;
$failedFields = array();
if (!array_key_exists("login", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "login"; }
if (!array_key_exists("passw", $_POST)) { $bRequiredParametersOK = false; $failedFields[] = "passw"; }
// Ahora comprobamos los campos obligatorios que vienen en el form!
if (!array_key_exists(ADirectory::USERFIELD_NAME, $_POST)) { $bRequiredParametersOK = false; $failedFields[] = ADirectory::USERFIELD_NAME; }
if (!array_key_exists(ADirectory::USERFIELD_SURNAME, $_POST)) { $bRequiredParametersOK = false; $failedFields[] = ADirectory::USERFIELD_SURNAME; }
if (!array_key_exists(ADirectory::USERFIELD_EMPLOYEETYPE, $_POST)) { $bRequiredParametersOK = false; $failedFields[] = ADirectory::USERFIELD_EMPLOYEETYPE; }
if ( $bRequiredParametersOK === false ) {
$resp = $this->generateErrorWithCode(4);
$resp["fields_required"] = array();
$resp["fields_required"][] = "login";
$resp["fields_required"][] = "passw";
$resp["fields_required"][] = ADirectory::USERFIELD_NAME;
$resp["fields_required"][] = ADirectory::USERFIELD_SURNAME;
$resp["fields_required"][] = ADirectory::USERFIELD_EMPLOYEETYPE;
$resp["fields_failed"] = $failedFields;
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > create_new_user > ERROR: < ".$json." >");
return;
}
// Ahora que ya hemos comprobado que todo va ok! Instanciamos el objeto que gestiona a active directory!
$adirectory = new ADirectory(MSAD_HOST,MSAD_USER,MSAD_PASS,MSAD_BASE,MSAD_DOMAIN);
if ( $adirectory->connect() === false ) {
$adirectory->close();
$json = json_encode($this->generateErrorWithCode(5));
echo $json;
Logger::write("CTRL USERS > create_new_user > ERROR: < ".$json." >");
return;
}
// Preparamos los campos que pasaremos a la funcion de crear
$login = trim($_POST["login"]);
$passw = trim($_POST["passw"]);
$params = array();
$params[ADirectory::USERFIELD_NAME] = $_POST[ADirectory::USERFIELD_NAME];
$params[ADirectory::USERFIELD_SURNAME] = $_POST[ADirectory::USERFIELD_SURNAME];
$params[ADirectory::USERFIELD_EMPLOYEETYPE] = $_POST[ADirectory::USERFIELD_EMPLOYEETYPE];
//if ( array_key_exists(ADirectory::USERFIELD_PROXYADDRESSES, $_POST)) {
// $params[ADirectory::USERFIELD_PROXYADDRESSES] = $_POST[ADirectory::USERFIELD_PROXYADDRESSES];
//}
// Actualmente el 3er parametro ---> BASE DN --> puede ser null, porque el EMPLOYEETYPE es quien nos dice a que DN irá
// el nuevo usuario, asi controlamos que no se hagan guarradas
$resultAD = $adirectory->createUser($login, $passw, NULL, $params);
$resp = array();
switch ($resultAD) {
case ADirectory::RV_OK:
case ADirectory::RV_ERROR_NOTPASSSET:
case ADirectory::RV_ERROR_NOTACTIVATED:
$resp = $this->generateResponse();
break;
default:
$resp = $this->generateErrorWithCode(6);
break;
}
$resp["adirectory"]["code"] = "".$resultAD;
$resp["adirectory"]["message"] = $adirectory->translateWsCodeToString($resultAD);
$json = json_encode($resp);
echo $json;
Logger::write("CTRL USERS > create_new_user > RESP: < ".$json." >");
$adirectory->close();
}
}
?>
Sobretodo me gustaria saber:
- Como manejais las diferentes versiones del webservice para las diferentes versiones de apps. Si por ejemplo cambian los requerimientos de un metodo para una versión a otra, como lo haceis para mantener las dos activas sin tener que comenzar a meter ifs por medio. Creais una carpeta con webservice/v1 webservice/v2 ?
- Aparte de preparedStatements y comprobar que los campos que son necesarios para ejecutar el método han sido enviados, que otras comprobaciones haceis (obviamente si un campo ha de ser un int, enum, etc, entiendo que haceis la comprobación tambien).
Etc..