PHP do Básico ao Avançado – Aula 12 – Outras Particularidades e Características da Linguagem

Tempo de Leitura: 11 Minutos

Neste ponto, vamos falar sobre outras dicas de segurança e também das limitações do PHP como linguagem e qual o perfil de sistemas onde ele melhor se enquadra. A segurança, é sempre uma questão recorrente, pois a cada novo passo que damos no aprendizado novas possibilidades são abertas e novas opções de segurança devem ser observadas, e como para um iniciante muitas vezes os conceitos de código limpo e seguro podem atrapalhar o entendimento da lógica, vamos evoluindo esses conceitos gradativamente.

Cada dado que é enviado e recebido entre páginas e entre requisições ou servidores, deve ser validado de outras maneiras. Sempre valide os dados enviados pelos usuário e inicialize suas variáveis! Para checar por variáveis não inicializadas, você pode configurar error_reporting() para mostrar erros do nível E_NOTICE, além de se souber de antemão a origem de uma variável, valide se ela veio de lá.

Um outro problema que vemos, é sobre performance, existem algumas diretivas que permitem que o interpretador PHP leia arquivos de entrada dos mais diversos formatos, como por exemplo arquivos com a extensão .htm ou .html isso acaba degradando a performance. Muitas pessoas acreditam que esconder a real linguagem onde o site ou sistema esta hospedado e escrito pode trazer uma segurança, até pode, você pode configurar arquivos de extensões diferentes, mais passar ao interpretador conteúdo estático é desnecessário e acaba prejudicando a performance.

A Arquitetura de um Sistema Baseado em Web

Em um sistema, baseado em web, temos uma sincronia entre diferentes softwares que são independentes e podem ou não estar rodando dentro de um mesmo servidor ou em servidores diferentes ou mesmo em um aninhado de servidores, tudo isso quem vai determinar é a necessidade e a quantidade de requisições que temos que atender.

Quando planejamos um sistema baseado em web, temos pelo menos os seguintes componentes, futuramente vamos detalhar melhor cada um deles:
-SERVIDOR HTTPD (HTTP e HTTPS) que é o responsável pelas requisições aos arquivos estáticos e a todo o conteúdo do servidor passado para o browser do cliente;
-PHP é a linguagem responsável pela interpretação dos seus scripts, e que deve estar configurada para responder as requisições pelo servidor HTTPD, e com todas as configurações do ambiente onde está sendo executado;
-SERVIDOS DE BANCO DE DADOS que é o responsável pelo tratamento dos dados e requisições e também deve estar configurado para responder as solicitações conforme a necessidade do ambiente;
-SISTEMA OPERACIONAL do servidor é o responsável pelo funcionamento central do servidor.

Além destes, outros serviços como servidores de email, ftp, e outros protocolos podem estar disponíveis e cada qual é independente, ou seja, você pode ter um sistema operacional diferente no servidor httpd, outro no servidor de banco de dados, o próprio servidor de banco de dados pode ser MySQL, MariaDB, PostgreeSQL, SQL SERVER, ORACLE, MongoDB, ou qualquer outro e cada qual possui características diferentes, o PHP pode ter centenas de configurações e recursos diferentes, o servidor web pode ser o Apache, o IIS, o LightHttpd, o NGINX e uma infinidade de outros, também cada qual com uma configuração e recursos diferentes. Viu que logo, são centenas de configurações e possibilidades diferentes? Que nem tudo depende somente do programador, outros profissionais podem ser especialistas em cada um destes segmentos e cada qual pode ser responsável por uma parte da configuração.

Uma boa prática é como em qualquer outro sistema, estar sobre constante revisão e melhoramento, cada versão nova de cada componente normalmente incluirá mudanças, sejam grandes ou pequenas, para melhorar a segurança e reparar falhas, erros de configuração, e outros problemas que podem afetar a segurança geral e estabilidade do sistema, a melhor política é atualizar frequentemente e manter-se atento as novas versões e suas mudanças. Manter a sua base de código sempre atualizada, e refletindo as novas diretrizes da comunidade, fechando novas brechas de segurança e testando a compatibilidade.

Diferente de um sistema que roda em um único computador, um sistema baseado na web, é aberto não somente aos usuários, como também a outras pessoas conectadas a essa rede, portanto a segurança e a atualização são tão importantes e o fato de poder ser distribuído em serviços menores ou em partes independentes aumentando o escalonamento e a disponibilidade também trazem novas questões e uma necessidade cada vez maior do profissional desenvolvedor conhecer as configurações do ambiente, possibilitando, integrar todos os pontos de maneira eficiente e com segurança.

Para que Servem COOKIES E SESSIONS

Como visto, anteriormente, um servidor HTTP/HTTPS só é capaz de permitir a troca de arquivos estáticos, ele não sabe quem esta conectado na outra ponta, simplesmente ele responde a requisição com um conteúdo, que pode ter sido gerado pelo PHP ou como um arquivo de imagem, de som ou qualquer outro arquivo.

O uso de cookies, permite, por exemplo, que o servidor receba uma pequena informação que permite ao servidor saber quem esta conectado do outro lado, trocando dados e identificando esse acesso como um identificador único. Do lado do servidos o PHP permite que essa informação seja associada a uma sessão, persistindo os dados do acesso como se fosse uma parte reservada, permitindo que esses mesmos dados estejam disponíveis em acessos e requisições subsequentes.

Essa é a maneira peculiar pela qual a duple COOKIES/SESSIONS é tratada no PHP e permite que você gerencie quem está conectado e através de qual conexão, gerando as respostas corretas e identificando o acesso e o controle de acesso e logins entre outras coisas. Outras linguagens também usam o cookie como parte da identificação do usuário, porém, mesmo sendo complexo a manipulação dos dois recursos, o PHP simplifica muito e garante uma boa segurança nesse tratamento de dados.

Lidando com a Manipulação de Arquivos

Uma outra peculiaridade do PHP é o tratamento de arquivos enviados através do método POST onde dependendo da configuração, é criado um array mágico chamado $_FILES que contem uma lista de todos os conteúdos postados e codificados pelo método enctype='multipart/form-data' isso é uma particularidade pois ele disponibiliza esse array de maneira simples.

Porém, pode ser um risco, se você não validar e eliminar conteúdo potencialmente perigoso antes de salvar ou executar este arquivo podendo expor falhas de segurança ou mesmo conteúdos maliciosos ou proibidos de serem disponibilizados.

Outros métodos como interligação com serviços de FTP ou outros protocolos e mesmo uso de encoders para transmissão podem ser usados e implementados, porém este formato simplifica muito e pode ser considerado um diferencial, já que a própria linguagem trata os erros da transferência, e disponibiliza de maneira quase transparente para o desenvolvedor.

Para funcionar corretamente e com maior segurança, é necessário que o programador conheça o funcionamento do sistema de arquivos, e das permissões de acesso do sistema operacional e do servidor httpd ou web. Além das limitações de tamanhos de arquivo, tempos de execução e outras configurações. Vamos abordar este processo mais a frente, em outra aula.

Uma outra opção é manipular arquivos remotos, você pode usar URLs HTTP e FTP com a maioria das funções que recebem um nome de arquivo como parâmetro, inclusive com INCLUDE e REQUIRE e este conteúdo pode ser de qualquer formato, seja um conteúdo estático ou um pré-processado ou mesmo um arquivo em php que será executado e analisado pelo interpretador local, o que pode ser uma facilidade ou abrir uma brecha na segurança, portanto você deve confiar no conteúdo do arquivo remoto.

Por exemplo, você pode usar isso para abrir um arquivo em um web server remoto, avaliar a saída para a informação que você precisa, e então usar a informação em uma query de banco de dados, ou simplesmente mostrar em um estilo que combine com o resto do seu website.

Você também pode escrever arquivos em um servidor FTP (presumindo que você conectou como um usuário com os direitos de acesso corretos). Você só pode criar arquivos novos usando esse método.

Tratamento de CONEXÕES

O PHP permite que de maneira simples, você verifique o estado de uma conexão, seja ela para o HTTP ou para qualquer outro protocolo. Existem 4 estados possíveis: 0 – NORMAL, 1 – ABORTED, 2 – TIMEOUT
3 – ABORTED and TIMEOUT

Quando um script PHP está sendo executado normalmente, o estado NORMAL está ativo. Se o cliente remoto desconecta, o estado ABORTED (abortado) é ligado. Uma desconexão do cliente remoto é normalmente causada pelo usuário apertando o botão STOP. Se o tempo limite imposto pelo PHP (veja set_time_limit()) é alcançado, o estado TIMEOUT (tempo acabado) é ligado.

Você pode decidir se quer ou não que a desconexão do cliente cause interrupção em seu script. As vezes é útil sempre fazer o seu script rodar até completar mesmo se não houver nenhum navegador remoto recebendo a saída. O comportamento padrão, no entanto, é de seu script ser interrompido quando o cliente remoto se desconecta. Esse comportamento pode ser configurado através da diretiva ignore_user_abort.

Note que ambos os estados ABORTED e TIMEOUT podem estar ligados ao mesmo tempo, isso é possível se você disser ao PHP para ignorar o abort do usuário e continuar á execução, até alcançar o tempo limite, ele será abortado e sua função de finalização, se existente, será chamada. Para este controle são usadas duas funções: connection_status() e register_shutdown_function() onde a primeira verifica o estatus, e a segunda é chamada quando um estado diferente de 0 é sinalizado.

Essas funções são muito úteis, por exemplo, se você precisa controlar quando um visitante em seu site faz um pedido e precisa verificar se ele não clicou no botão enviar duas vezes ou cancelou o envio logo após clicar no botão enviar. Se o seu visitante clicar no botão parar logo após o envio, seu script pode parar no meio do processo de cadastramento dos produtos e não finalizar a lista, gerando inconsistência em seu banco de dados. Para evitar um duplo clique no botão enviar, você pode desabilitá-lo com javascript ou em seu script você pode definir um sinalizador para aquele pedido, que será registrado no banco de dados. Antes de aceitar um novo envio, o script verificará se o mesmo pedido não foi feito antes e o rejeitará. No início do script, você pode especificar uma função de callback que agirá como a função de desligamento quando ele terminar e também permitirá que você trabalhe na página gerada antes de enviá-la para o visitante.

Conexões Persistentes ao Banco de Dados

Conexões persistentes são conexões que não fecham quando a execução do seu script termina. Quando uma conexão persistente é requisitada, o PHP sozinho verifica se já existe uma conexão persistente idêntica que foi aberta anteriormente e, se ela existir, ele a usa. Se ela não existir, ele cria a conexão.

Pessoas que não são totalmente familiarizadas com a maneira como servidores web trabalham e distribuem a carga podem confundir conexões persistentes. Em particular, elas não dão a você a capacidade de abrir ‘sessões de usuários’ na mesma conexão, elas não dão a você a capacidade de construir uma transação eficientemente, para ser extremamente claro, elas não te dão nenhuma funcionalidade que não era possível com as suas correspondentes não-persistentes.

Quando o PHP é executado como um CGI, a cada requisição é criada uma instância do interpretador do PHP e destruída para cada requisição ou seja, nesta situação não existe a persistência. Quando o PHP roda como um módulo do servidor, que é onde temos a melhor performance, porém até o momento isso é compatível somente com uma parte dos servidores como o Apache, o servidor cria um processo (pai) que controla uma série de processos menores (filhos) que realmente fazem o trabalho de servir as páginas web. Quando uma requisição chega de um cliente, ela é entregue à um dos filhos que já não estiver servindo outro cliente. Isso significa que quando o mesmo cliente faz uma segunda requisição para o servidor, ele pode ser atendido por um processo filho diferente do que da primeira vez. Ao abrir uma conexão persistente, cada página que requisitar serviços de SQL pode reutilizar a mesma conexão estabelecida ao servidor SQL.

Para que elas servem?

Eficiência, conexões persistentes são boas se a sobrecarga (overhead) para criar uma conexão ao seu servidor SQL for alta, por exemplo para abrir conexões onde é necessário resolver um nome de host, ou o tempo de resposta do DNS/HOST for mais alto que uma conexão local (localhost ou 127.0.0.1). Se essa sobrecarga é alta ou não depende de vários fatores como, qual tipo de banco de dados, se está ou não na mesma máquina onde o servidor web está, o quão carregada a máquina onde está o servidor SQL está e assim por diante. O ponto é que se a sobrecarga de conexão for alta, conexões persistentes ajudam consideravelmente. Elas fazem com que os processos filhos simplesmente se conectem uma vez só durante toda sua duração, ao invés de cada vez que eles processam uma página que requer uma conexão ao servidor SQL. Isso significa que cada filho que abriu uma conexão persistente terá sua própria conexão persistente para o servidor. Por exemplo, se você tivesse 20 processos filhos diferentes que rodassem um script que fizesse uma conexão persistente à um servidor SQL, você teria 20 conexões diferentes servidor SQL, uma para cada filho.

Perceba, no entanto, que isso pode ter algumas desvantagens se você estiver usando um banco de dados com limite de conexões que são excedidas pela conexões persistentes dos filhos. Se o seu banco de dados tem um limite de 16 conexões simultâneas, e durante um momento de pico de acessos, 17 processos filhos tentarem se conectar, um deles não será capaz. Se houver bugs no seus scripts que não permitem que as conexões se fechem (como loops infinitos) o banco de dados com apenas 16 conexões pode rapidamente ficar sobrecarregado.

Alguns cuidados devem ser tomados, como fechamento e limpeza dos dados de conexão, e travamentos de tabelas (lock) que podem comprometer a performance mais do que ajudar, ou causar uma sobrecarga de ambos os servidores, portanto, a regra é sempre crie scripts onde a execução possa ser persistente ou não, e não dependa disso, desse modo, você consegue fazer testes de performance em todas as plataformas antes de optar por uma ou pela outra.

Conclusão

Nesta aula, vemos que o PHP possui peculiaridades e facilitadores que se bem utilizados podem acelerar muito o tempo de desenvolvimento, e simplificar o uso de recursos no lado do servidor, servindo como um facilitador de grande parte do trabalho pesado e se adequando a maioria dos projetos baseados em bases de dados relacionais.

Como o PHP é uma linguagem voltada especificamente a tratamento e requisições de rede, e manipulação de servidores httpd, ele pode ser usado não somente para gerar saídas para o browser do usuário, como para executar tarefas específicas como abertura de conexões e tratamento de arquivos, e uma série de outras, através da sua interface, sendo chamado diretamente como um script de linha de comando. Na próxima aula, vamos falar sobre esses possíveis usos, dando exemplos de sua implementação, e também como é simples usar o PHP em tarefas mais complexas em outras linguagens, como tratamento de autenticação diretamente pelo método http, e manipulação de dados e cabeçalhos de execução.