├── .htaccess ├── .http ├── alteracoes ├── parte-01.zip ├── parte-02.zip ├── parte-03.zip ├── parte-04.zip ├── parte-05.zip ├── parte-06.zip ├── parte-07.rar └── parte-08.zip ├── classes ├── autoload.class.php ├── clientes.class.php ├── db.class.php ├── jwt.class.php ├── rotas.class.php └── usuarios.class.php ├── database.sql └── index.php /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteCond %{REQUEST_FILENAME} !-f 3 | RewriteCond %{REQUEST_FILENAME} !-d 4 | RewriteRule ^(.*)$ index.php?path=$1 [QSA,L] -------------------------------------------------------------------------------- /.http: -------------------------------------------------------------------------------- 1 | POST http://localhost/php_api/usuarios/login HTTP/1.1 2 | Content-Type: application/x-www-form-urlencoded 3 | 4 | login=netocosta 5 | &senha=123456 6 | 7 | ### 8 | 9 | GET http://localhost/financas/api/clientes/listar HTTP/1.1 10 | Authorization: Bearer 11 | 12 | ### 13 | 14 | GET http://localhost/php_api/clientes/listar/55 HTTP/1.1 15 | Authorization: Bearer 16 | 17 | ### 18 | 19 | POST http://localhost/php_api/clientes/atualizar/1 HTTP/1.1 20 | Authorization: Bearer 21 | Content-Type: application/x-www-form-urlencoded 22 | 23 | _method=PUT 24 | &nome=Costa Neto -------------------------------------------------------------------------------- /alteracoes/parte-01.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-01.zip -------------------------------------------------------------------------------- /alteracoes/parte-02.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-02.zip -------------------------------------------------------------------------------- /alteracoes/parte-03.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-03.zip -------------------------------------------------------------------------------- /alteracoes/parte-04.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-04.zip -------------------------------------------------------------------------------- /alteracoes/parte-05.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-05.zip -------------------------------------------------------------------------------- /alteracoes/parte-06.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-06.zip -------------------------------------------------------------------------------- /alteracoes/parte-07.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-07.rar -------------------------------------------------------------------------------- /alteracoes/parte-08.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netocosta/php_api/fe5c745ac4fa26dd042c88d9fe4546c4bdbbfd6f/alteracoes/parte-08.zip -------------------------------------------------------------------------------- /classes/autoload.class.php: -------------------------------------------------------------------------------- 1 | prepare("SELECT * FROM clientes ORDER BY nome"); 9 | $rs->execute(); 10 | $obj = $rs->fetchAll(PDO::FETCH_ASSOC); 11 | 12 | if ($obj) { 13 | echo json_encode(["dados" => $obj]); 14 | } else { 15 | echo json_encode(["dados" => 'Não existem dados para retornar']); 16 | } 17 | } 18 | 19 | public function listarUnico($param) 20 | { 21 | //var_dump("Parametro: ".$param); 22 | 23 | $db = DB::connect(); 24 | $rs = $db->prepare("SELECT * FROM clientes WHERE id={$param}"); 25 | $rs->execute(); 26 | $obj = $rs->fetchObject(); 27 | 28 | if ($obj) { 29 | echo json_encode(["dados" => $obj]); 30 | } else { 31 | echo json_encode(["dados" => 'Não existem dados para retornar']); 32 | } 33 | } 34 | 35 | public function adicionar() 36 | { 37 | $sql = "INSERT INTO clientes ("; 38 | $contador = 1; 39 | foreach (array_keys($_POST) as $indice) { 40 | if (count($_POST) > $contador) { 41 | $sql .= "{$indice},"; 42 | } else { 43 | $sql .= "{$indice}"; 44 | } 45 | $contador++; 46 | } 47 | $sql .= ") VALUES ("; 48 | $contador = 1; 49 | foreach (array_values($_POST) as $valor) { 50 | if (count($_POST) > $contador) { 51 | $sql .= "'{$valor}',"; 52 | } else { 53 | $sql .= "'{$valor}'"; 54 | } 55 | $contador++; 56 | } 57 | $sql .= ")"; 58 | 59 | $db = DB::connect(); 60 | $rs = $db->prepare($sql); 61 | $exec = $rs->execute(); 62 | 63 | if ($exec) { 64 | echo json_encode(["dados" => 'Dados foram inseridos com sucesso.']); 65 | } else { 66 | echo json_encode(["dados" => 'Houve algum erro ao inseris os dados.']); 67 | } 68 | } 69 | 70 | public function atualizar($param) 71 | { 72 | array_shift($_POST); 73 | 74 | $sql = "UPDATE clientes SET "; 75 | 76 | $contador = 1; 77 | foreach (array_keys($_POST) as $indice) { 78 | if (count($_POST) > $contador) { 79 | $sql .= "{$indice} = '{$_POST[$indice]}', "; 80 | } else { 81 | $sql .= "{$indice} = '{$_POST[$indice]}' "; 82 | } 83 | $contador++; 84 | } 85 | 86 | $sql .= "WHERE id={$param}"; 87 | 88 | $db = DB::connect(); 89 | $rs = $db->prepare($sql); 90 | $exec = $rs->execute(); 91 | 92 | if ($exec) { 93 | echo json_encode(["dados" => 'Dados atualizados com sucesso.']); 94 | } else { 95 | echo json_encode(["dados" => 'Houve erro ao atualizar dados.']); 96 | } 97 | } 98 | 99 | public function deletar($param) 100 | { 101 | $db = DB::connect(); 102 | $rs = $db->prepare("DELETE FROM clientes WHERE id={$param}"); 103 | $exec = $rs->execute(); 104 | 105 | if ($exec) { 106 | echo json_encode(["dados" => 'Dados foram excluidos com sucesso.']); 107 | } else { 108 | echo json_encode(["dados" => 'Houve algum erro ao excluir os dados.']); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /classes/db.class.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class JWT 13 | { 14 | /** 15 | * @param string $jwt The JWT 16 | * @param string|null $key The secret key 17 | * @param bool $verify Don't skip verification process 18 | * 19 | * @return object The JWT's payload as a PHP object 20 | */ 21 | 22 | public static function decode($jwt, $key = null, $verify = true) 23 | { 24 | $tks = explode('.', $jwt); 25 | if (count($tks) != 3) { 26 | throw new UnexpectedValueException('Wrong number of segments'); 27 | } 28 | list($headb64, $payloadb64, $cryptob64) = $tks; 29 | if (null === ($header = JWT::jsonDecode(JWT::urlsafeB64Decode($headb64))) 30 | ) { 31 | throw new UnexpectedValueException('Invalid segment encoding'); 32 | } 33 | if (null === $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($payloadb64)) 34 | ) { 35 | throw new UnexpectedValueException('Invalid segment encoding'); 36 | } 37 | $sig = JWT::urlsafeB64Decode($cryptob64); 38 | if ($verify) { 39 | if (empty($header->alg)) { 40 | throw new DomainException('Empty algorithm'); 41 | } 42 | if ($sig != JWT::sign("$headb64.$payloadb64", $key, $header->alg)) { 43 | throw new UnexpectedValueException('Signature verification failed'); 44 | } 45 | } 46 | return $payload; 47 | } 48 | 49 | /** 50 | * @param object|array $payload PHP object or array 51 | * @param string $key The secret key 52 | * @param string $algo The signing algorithm 53 | * 54 | * @return string A JWT 55 | */ 56 | public static function encode($payload, $key, $algo = 'HS256') 57 | { 58 | $header = array('typ' => 'JWT', 'alg' => $algo); 59 | 60 | $segments = array(); 61 | $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($header)); 62 | $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($payload)); 63 | $signing_input = implode('.', $segments); 64 | 65 | $signature = JWT::sign($signing_input, $key, $algo); 66 | $segments[] = JWT::urlsafeB64Encode($signature); 67 | 68 | return implode('.', $segments); 69 | } 70 | 71 | /** 72 | * @param string $msg The message to sign 73 | * @param string $key The secret key 74 | * @param string $method The signing algorithm 75 | * 76 | * @return string An encrypted message 77 | */ 78 | public static function sign($msg, $key, $method = 'HS256') 79 | { 80 | $methods = array( 81 | 'HS256' => 'sha256', 82 | 'HS384' => 'sha384', 83 | 'HS512' => 'sha512', 84 | ); 85 | if (empty($methods[$method])) { 86 | throw new DomainException('Algorithm not supported'); 87 | } 88 | return hash_hmac($methods[$method], $msg, $key, true); 89 | } 90 | 91 | /** 92 | * @param string $input JSON string 93 | * 94 | * @return object Object representation of JSON string 95 | */ 96 | public static function jsonDecode($input) 97 | { 98 | $obj = json_decode($input); 99 | if (function_exists('json_last_error') && $errno = json_last_error()) { 100 | JWT::handleJsonError($errno); 101 | } else if ($obj === null && $input !== 'null') { 102 | throw new DomainException('Null result with non-null input'); 103 | } 104 | return $obj; 105 | } 106 | 107 | /** 108 | * @param object|array $input A PHP object or array 109 | * 110 | * @return string JSON representation of the PHP object or array 111 | */ 112 | public static function jsonEncode($input) 113 | { 114 | $json = json_encode($input); 115 | if (function_exists('json_last_error') && $errno = json_last_error()) { 116 | JWT::handleJsonError($errno); 117 | } else if ($json === 'null' && $input !== null) { 118 | throw new DomainException('Null result with non-null input'); 119 | } 120 | return $json; 121 | } 122 | 123 | /** 124 | * @param string $input A base64 encoded string 125 | * 126 | * @return string A decoded string 127 | */ 128 | public static function urlsafeB64Decode($input) 129 | { 130 | $remainder = strlen($input) % 4; 131 | if ($remainder) { 132 | $padlen = 4 - $remainder; 133 | $input .= str_repeat('=', $padlen); 134 | } 135 | return base64_decode(strtr($input, '-_', '+/')); 136 | } 137 | 138 | /** 139 | * @param string $input Anything really 140 | * 141 | * @return string The base64 encode of what you passed in 142 | */ 143 | public static function urlsafeB64Encode($input) 144 | { 145 | return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); 146 | } 147 | 148 | /** 149 | * @param int $errno An error number from json_last_error() 150 | * 151 | * @return void 152 | */ 153 | private static function handleJsonError($errno) 154 | { 155 | $messages = array( 156 | JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', 157 | JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', 158 | JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', 159 | ); 160 | throw new DomainException(isset($messages[$errno]) 161 | ? $messages[$errno] 162 | : 'Unknown JSON error: ' . $errno 163 | ); 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /classes/rotas.class.php: -------------------------------------------------------------------------------- 1 | listaRotas[] = strtoupper($metodo).':'.$rota; 12 | $this->listaCallback[] = $callback; 13 | $this->listaProtecao[] = $protecao; 14 | 15 | return $this; 16 | } 17 | 18 | public function ir($rota) 19 | { 20 | $param = ''; 21 | $callback = ''; 22 | $protecao = ''; 23 | $methodServer = $_SERVER['REQUEST_METHOD']; 24 | $methodServer = isset($_POST['_method']) ? $_POST['_method'] : $methodServer; 25 | $rota = $methodServer.":/".$rota; 26 | 27 | 28 | if (substr_count($rota, "/") >= 3) { 29 | $param = substr($rota, strrpos($rota, "/")+1); 30 | $rota = substr($rota, 0, strrpos($rota, "/"))."/[PARAM]"; 31 | } 32 | 33 | $indice = array_search($rota, $this->listaRotas); 34 | if ($indice > 0) { 35 | $callback = explode("::", $this->listaCallback[$indice]); 36 | $protecao = $this->listaProtecao[$indice]; 37 | } 38 | 39 | $class = isset($callback[0]) ? $callback[0] : ''; 40 | $method = isset($callback[1]) ? $callback[1] : ''; 41 | 42 | 43 | if (class_exists($class)) 44 | { 45 | if (method_exists($class, $method)) 46 | { 47 | $instanciaClass = new $class(); 48 | if ($protecao) { 49 | $verificacao = new Usuarios(); 50 | if ($verificacao->verificar()) { 51 | return call_user_func_array( 52 | array($instanciaClass, $method), 53 | array($param) 54 | ); 55 | } else { 56 | echo json_encode(["dados" => "token invalido."]); 57 | } 58 | } else { 59 | return call_user_func_array( 60 | array($instanciaClass, $method), 61 | array($param) 62 | ); 63 | } 64 | } else { 65 | $this->naoExiste(); 66 | } 67 | } else { 68 | $this->naoExiste(); 69 | } 70 | 71 | } 72 | 73 | public function naoExiste() 74 | { 75 | http_response_code(404); 76 | } 77 | } -------------------------------------------------------------------------------- /classes/usuarios.class.php: -------------------------------------------------------------------------------- 1 | 'Falta informacoes!']); 10 | exit; 11 | } else { 12 | $login = addslashes(htmlspecialchars($_POST['login'])) ?? ''; 13 | $senha = addslashes(htmlspecialchars($_POST['senha'])) ?? ''; 14 | $secretJWT = $GLOBALS['secretJWT']; 15 | 16 | $db = DB::connect(); 17 | $rs = $db->prepare("SELECT * FROM usuarios WHERE login = '{$login}'"); 18 | $exec = $rs->execute(); 19 | $obj = $rs->fetchObject(); 20 | $rows = $rs->rowCount(); 21 | 22 | if ($rows > 0) { 23 | $idDB = $obj->id; 24 | $nameDB = $obj->nome; 25 | $passDB = $obj->senha; 26 | $validUsername = true; 27 | $validPassword = password_verify($senha, $passDB) ? true : false; 28 | } else { 29 | $validUsername = false; 30 | $validPassword = false; 31 | } 32 | 33 | if ($validUsername and $validPassword) { 34 | //$nextWeek = time() + (7 * 24 * 60 * 60); 35 | $expire_in = time() + 60000; 36 | $token = JWT::encode([ 37 | 'id' => $idDB, 38 | 'name' => $nameDB, 39 | 'expires_in' => $expire_in, 40 | ], $GLOBALS['secretJWT']); 41 | 42 | $db->query("UPDATE usuarios SET token = '$token' WHERE id = $idDB"); 43 | echo json_encode(['token' => $token, 'data' => JWT::decode($token, $secretJWT)]); 44 | } else { 45 | if (!$validPassword) { 46 | echo json_encode(['ERROR', 'invalid password']); 47 | } 48 | } 49 | } 50 | } else { 51 | echo json_encode(['ERRO' => 'Falta informacoes!']); 52 | exit; 53 | } 54 | } 55 | 56 | public function verificar() 57 | { 58 | $headers = apache_request_headers(); 59 | if (isset($headers['authorization'])) { 60 | $token = str_replace("Bearer ", "", $headers['authorization']); 61 | } else if (isset($headers['Authorization'])) { 62 | $token = str_replace("Bearer ", "", $headers['Authorization']); 63 | } else { 64 | echo json_encode(['ERRO' => 'Você não está logado, ou seu token é inválido.']); 65 | exit; 66 | } 67 | 68 | $db = DB::connect(); 69 | $rs = $db->prepare("SELECT * FROM usuarios WHERE token = '{$token}'"); 70 | $exec = $rs->execute(); 71 | $obj = $rs->fetchObject(); 72 | $rows = $rs->rowCount(); 73 | $secretJWT = $GLOBALS['secretJWT']; 74 | 75 | if ($rows > 0) : 76 | $idDB = $obj->id; 77 | $tokenDB = $obj->token; 78 | 79 | $decodedJWT = JWT::decode($tokenDB, $secretJWT); 80 | if ($decodedJWT->expires_in > time()) { 81 | return true; 82 | } else { 83 | $db->query("UPDATE usuarios SET token = '' WHERE id = $idDB"); 84 | return false; 85 | } 86 | else : 87 | return false; 88 | endif; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /database.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS `clientes` ( 2 | `id` int NOT NULL AUTO_INCREMENT, 3 | `nome` text, 4 | PRIMARY KEY (`id`), 5 | KEY `id` (`id`) 6 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3; 7 | 8 | INSERT INTO `clientes` (`id`, `nome`) VALUES 9 | (1, 'Sucre Doceria'); 10 | 11 | CREATE TABLE IF NOT EXISTS `usuarios` ( 12 | `id` int NOT NULL AUTO_INCREMENT, 13 | `login` text, 14 | `senha` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, 15 | `nome` text NOT NULL, 16 | `token` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci, 17 | PRIMARY KEY (`id`), 18 | KEY `id` (`id`) 19 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3; 20 | 21 | INSERT INTO `usuarios` (`id`, `login`, `senha`, `nome`, `token`) VALUES 22 | (1, 'netocosta', '$2y$10$2EP57Bbpv1RTwuL3.e3b6u/4iylIzSmjbcUkhd2tBzo//v4IW6GcO', 'Neto Costa', ''); -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | add('POST', '/usuarios/login', 'Usuarios::login', false); 18 | $rota->add('GET', '/clientes/listar', 'Clientes::listarTodos', true); 19 | $rota->add('GET', '/clientes/listar/[PARAM]', 'Clientes::listarUnico', true); 20 | $rota->add('POST', '/clientes/adicionar', 'Clientes::adicionar', true); 21 | $rota->add('PUT', '/clientes/atualizar/[PARAM]', 'Clientes::atualizar', true); 22 | $rota->ir($_GET['path']); 23 | --------------------------------------------------------------------------------