Melhore a segurança e o desempenho de aplicativos DB2 Ruby on Rails usando consultas parametrizadas

O novo adaptador ActiveRecord para DB2

Com o crescente interesse em Ruby on Rails em empresas do mundo corporativo, alguns observadores questionaram sua adequação em relação aos requisitos exigentes dessa arena. Uma questão que tem chamado a atenção é que o ActiveRecord, o Object-Relational Mapper (ORM) do Rails, não usa instruções preparadas — ou, pelo menos, não usava até agora. Com o release mais recente do DB2® on Rails, consultas parametrizadas estão automaticamente disponíveis e trazem com elas importantes benefícios de desempenho e segurança para os aplicativos Rails.

Antonio Cangiano, Software Engineer and Technical Evangelist, IBM

Antonio Cangiano photoAntonio Cangiano trabalha como software engineer e technical evangelist na equipe do DB2 no IBM Toronto Software Lab. Ele foi o desenvolvedor original do adaptador Rails para DB2 e um dos líderes da comunidade DB2 on Rails. Ele é bastante conhecido nas comunidades Ruby and Rails e escreveu um livro sobre o assunto em 2009 para a Wrox, Ruby on Rails for Microsoft Developers. É possível ler mais matérias de Antonio no seu blog, Zen and the Art of Programming.



05/Mar/2010

O Ruby on Rails conseguiu se estabelecer como uma das estruturas mais frequentemente usadas para o desenvolvimento de aplicativos da Web. Lançado em 2004, esta estrutura evoluiu rapidamente e atraiu uma quantidade impressionante de atenção da mídia, bem como um grande número de fãs dentro da comunidade de desenvolvimento.

Em apenas alguns anos, Rails (como é usualmente referido) evoluiu de uma ferramenta de última geração que tinha alguns poucos usuários precoces e empresas iniciantes adotavam para uma ferramenta madura, cujas alegações de produtividade recentemente começaram a fascinar um grupo de pessoas mais "corporativo".

Rails e a empresa

Ao discutir esse assunto, uma questão que é frequentemente levantada pelos mais céticos entre nós é se o Rails está pronto para o ambiente empresarial. O Rails não se desculpa por ser um software pragmático e dogmático. Ele não pretende agradara todos, particularmente às empresas, onde é algumas vezes percebido como sendo muito orientado a processos e demasiadamente complexo. As necessidades das empresas corporativas e as da equipe de desenvolvimento do Rails tendem a ser consideravelmente diferentes. Portanto, é pouco provável que a equipe de desenvolvimento disponibilize os recursos requisitados pelas empresas.

No entanto, vale a pena redefinir este assunto perguntando se o mundo corporativo está pronto para o Rails. Nos últimos anos, o mundo corporativo começou a abraçar o movimento do desenvolvimento ágil, bem como ferramentas mais leves, mas ainda existem requisitos não negociáveis que tornariam o Ruby on Rails uma ferramenta menos que ideal em vários cenários.

Felizmente, o Rails fornece um sistema de complementos que permitiu a criação de milhares de plug-ins (que foram desenvolvidos pela comunidade para atender a todos os tipos de requisitos). No entanto, o Rails tende fundamentalmente a aplicar o princípio de fazer "aquilo que for mais simples e que possivelmente funcione", em nítido contraste com a abordagem muitas vezes preferida pelas empresas.

Por exemplo, SQLite e MySQL podem ser populares e suficientes para alguns desenvolvedores de software livre, mas desenvolvedores corporativos se interessam muito mais em um suporte bem sólido para bancos de dados comerciais como DB2 e Oracle.

A IBM® ingressou nesse ambiente bem cedo para catalisar a convergência desses dois mundos. Na verdade, a IBM é o único fornecedor de banco de dados que fornece e suporta comercialmente um driver para Ruby e um adaptador Rails para DB2 e IBM Informix® Dynamic Server (IDS). Ao fazer isso, várias empresas que usam o DB2 em sua infraestrutura puderam desenvolver novos aplicativos usando Ruby on Rails. A dupla conhecida como "DB2 on Rails" também funciona muito bem para desenvolvedores de software livre e empresas iniciantes que desejam combinar um servidor de dados poderoso, escalável, confiável (e gratuito, na sua edição Express-C) com a simplicidade de escrever aplicativos em Ruby on Rails.

Hoje, com o anúncio da Versão 2.0 do adaptador do Rails, o DB2 também se tornou o único banco de dados que suporta transparentemente consultas parametrizadas no Rails (sem a necessidade de modificar o código do aplicativo). Esse fato tem implicações profundas de desempenho e segurança, e é um importante passo à frente para qualquer desenvolvedor que use o Rails juntamente com o DB2.


Consultas parametrizadas e ActiveRecord

Nos bastidores, um aplicativo da Web típico executa um grande número de consultas similares repetidas vezes. Em alguns casos, o que muda não é a consulta em si, mas sim os valores usados por ela. Por exemplo, as seguintes consultas da Listagem 1 são idênticas, exceto pelo nome solicitado:

Listagem 1. Consultas SQL similares
SELECT * FROM people WHERE name = 'Antonio'
SELECT * FROM people WHERE name = 'Leon'
SELECT * FROM people WHERE name = 'Praveen'
SELECT * FROM people WHERE name = 'Mario'

Todas elas podem ser condensadas em uma única consulta parametrizada (também conhecida como uma instrução preparada), conforme mostrado na Listagem 2:

Listagem 2. Consulta parametrizada
SELECT * FROM people WHERE name = ?

O valor real é passado em tempo de execução para a consulta pré-compilada como um parâmetro. A consulta em si e seu plano de acesso são armazenados em cache uma vez pelo DB2 e então estarão prontas para serem usadas todas as vezes que a consulta for executada. Esse mecanismo melhora o desempenho principalmente porque o banco de dados poupa todo o custo adicional envolvido com o cálculo do plano de execução para a mesma consulta inúmeras vezes. Se essa consulta (ou uma mais complexa) forem repetidas algumas centenas (ou milhares) de vezes, a diferença entre a duas abordagens começaria a ficar bastante drástica.

Os aplicativos Rails usam ActiveRecord, uma estrutura Object-Relational Mapper (ORM), para tratar conexões e consultas de bancos de dados. O ActiveRecord não suporta consultas parametrizadas por padrão. Isso significa que cada consulta é construída combinando dinamicamente a entrada do usuário (que normalmente é devidamente verificada) e em seguida é executada como uma consulta em si. Por exemplo, o ActiveRecord traduz as seguintes chamadas de métodos (Listagem 3) nas consultas distintas mencionadas acima (consulte a Listagem 1):

Listagem 3. ActiveRecord equivalente à Listagem 1
Person.find_by_name('Antonio')
Person.find_by_name('Leon')
Person.find_by_name('Praveen')
Person.find_by_name('Mario')

Graças ao último gem do Ruby para o DB2 on Rails (denominado ibm_db), cada uma dessas consultas é tratada pelo adaptador ActiveRecord (que foi desenvolvido pela IBM para o DB2) de uma maneira que cuida da criação de uma única consulta parametrizada que está instantaneamente pronta para ser reutilizada. Além do desempenho, consultas parametrizadas são excelentes para evitar ataques de injeção de SQL. Os parâmetros são visualizados como valores que são passados para a consulta e que não tem nenhum efeito na estrutura da consulta em si. Como tal, truques espertos com aspas e caracteres especiais que algumas vezes são utilizados por usuários maliciosos em uma tentativa de modificar dinamicamente a estrutura da consulta tornam-se fúteis.

O ActiveRecord já faz um bom trabalho no que se refere a verificar a entrada do usuário, desde que o desenvolvedor preste atenção e utilize as ferramentas corretas fornecidas pela estrutura. Por exemplo, a instrução seguinte (Listagem 4) será corretamente verificada contra injeções diretas de SQL pelo ActiveRecord:

Listagem 4. Tratamento seguro da entrada no ActiveRecord
User.find(:all, :conditions => ["role = ? AND age > ?", role, age])

Se um desenvolvedor pouco cuidadoso inserisse o texto da Listagem 5 (na esperança de integrar os valores diretamente), a chamada estaria exposta a ataques de injeção de SQL:

Listagem 5. Tratamento inseguro da entrada no ActiveRecord
# Don't do this
User.find(:all, :conditions => "role = '#{role}' AND age > #{age}")

Se fosse esse o caso, a consulta seria na verdade construída dinamicamente, dependendo dos valores de função e idade. Por exemplo, a idade poderia ser a cadeia de caracteres "18 OR 1=1" e a consulta se transformaria em algo semelhante a:

Listagem 6. Um ataque de injeção SQL
SELECT * FROM users WHERE role = 'user' AND age > 18 OR 1=1

Essa consulta recuperaria registros que você não pretendia expor.

Esse é um motivo suficiente para que os desenvolvedores sempre optem pelas opções seguras fornecidas pelo ActiveRecord para verificar a entrada (como mostrado na Listagem 4). Esta nova edição de DB2 on Rails adiciona uma camada extra de segurança, graças ao fato de que essas chamadas "seguras" são traduzidas em consultas parametrizadas, que são imunes aos ataques de injeção SQL. Com o DB2, você tem a paz de espírito de saber que se um hacker esperto conseguir burlar o processo de verificação adotado pelo ActiveRecord, esses caracteres extra ou aspas mal intencionadas não alterariam a natureza de sua consulta.


Instalando ou atualizando para o ibm_db 2.0.0

Para aproveitar a consultas parametrizadas no Rails, não é necessário modificar qualquer código dentro do aplicativo. Basta seguir duas etapas simples para ativar esse novo recurso:

  • Instale a última versão do gem Ruby para DB2 on Rails (conhecido como ibm_db)
  • Modifique o arquivo de configuração do banco de dados do aplicativo

Vamos começar.

Se você for um usuário Microsoft® Windows®, basta simplesmente instalar o gem executando o comando a seguir a partir do prompt de comando:

Listagem 7. Instalando o gem ibm_db no Windows
C:\> gem install ibm_db

Se você for um usuário Linux® ou UNIX®, precisa especificar onde estão localizados os cabeçalhos de desenvolvimento antes de instalar o gem, da seguinte maneira:

Listagem 8. Instalando o gem ibm_db no Linux/AIX®
$ sudo -s
$ export IBM_DB_INCLUDE=/home/db2inst1/sqllib/include
$ export IBM_DB_LIB=/home/db2inst1/sqllib/lib
$ . /home/db2inst1/sqllib/db2profile
$ gem install ibm_db

(Usuários 64-bit devem apontar para a biblioteca lib64).

Se você for um desenvolvedor no Mac OS X 10.5 (Leopard), poderá instalar o gem de forma semelhante, como segue:

Listagem 9. Instalando o gem ibm_db no Mac OS X 10.5
$ sudo -s
$ export IBM_DB_LIB=/Users/<username>/sqllib/lib
$ export IBM_DB_INCLUDE=/Users/<username>/sqllib/include
$ . /Users/<username>/sqllib/db2profile
$ gem install ibm_db

Mas, se você for um usuário do Mac OS X 10.6 (Snow Leopard), deverá executar:

Listagem 10. Instalando o gem ibm_db no Mac OS X 10.6
$ sudo -s
$ export IBM_DB_LIB=/Users/<username>/sqllib/lib64
$ export IBM_DB_INCLUDE=/Users/<username>/sqllib/include
$ export ARCHFLAGS="-arch x86_64"
$ gem install ibm_db

Todas essas instruções instalam o gem ou o atualizam para a versão mais atual, caso uma mais antiga tenha sido instalada previamente. Se o comando gem install apresentar um problema com a versão instalada do RubyGems, é possível executar o comando a seguir para atualizar o próprio gerenciador de pacotes:

Listagem 11. Atualizando o RubyGems
 $ gem update --system

Ativando consultas parametrizadas em aplicativos Rails existentes

Os aplicativos Rails atualizam a configuração de banco de dados em um arquivo localizado em config/database.yml. Para ativar consultas parametrizadas em um determinado aplicativo, especifique o parâmetro parameterized. Por exemplo:

Listagem 12. Um fragmento de exemplo de configuração para um único ambiente
production:
  adapter: ibm_db
  username: db2inst1
  password: secret
  database: mydb
  parameterized: true

Se este parâmetro de configuração não for definido o adaptador ActiveRecord para DB2 continuará a trabalhar como as versões anteriores, sem transformar consultas regulares em parametrizadas. Ao fazer isso, torna-se fácil avaliar rapidamente os ganhos de desempenho e decidir se esta opção deve ser mantida ativada ou não no modo de produção.


Considerações de desempenho

É claro que você deve sempre executar suas próprias avaliações de desempenho, mas testes em nosso laboratório mostraram que a ativação de consultas parametrizadas causou uma melhora considerável de desempenho. Os benefícios das instruções preparadas são claramente destacados com um aumento na carga de trabalho. O gráfico da Figura 1 mostra os resultados obtidos ao testar uma carga de trabalho relativamente pesada com e sem a ativação de consultas parametrizadas, bem como com o Statement Concentrator ativado.

Figura 1. Resultados da avaliação de desempenho
Resultados da avaliação de desempenho

Como se pode ver, a ativação de consultas parametrizadas aumentou o rendimento do banco de dados em cerca de 30% a 40%, e até ofereceu um aumento de 15% a 25% sobre a ativação do Statement Concentrator. O Statement Concentrator pode ser encarado como uma etapa intermediária. É um recurso que tenta emular os benefícios das instruções preparadas no nível do servidor de dados reduzindo os custos adicionais da compilação compartilhando o mesmo plano de acesso para consultas que sejam idênticas (exceto os valores dos literais). É um recurso excelente que somente está disponível no DB2 9.7 e que deve ser ativado se as consultas parametrizadas não estiverem disponíveis em uma determinada estrutura de desenvolvimento. Felizmente, de agora em diante, os desenvolvedores de DB2 on Rails não terão que se preocupar com isso.


Conclusão

O anúncio desta nova versão do gem ibm_db gem um dos muito poucos (embora altamente importante) defeitos do Rails e deve ser encarado como boas notícias por qualquer pessoa que esteja interessada em combinar a simplicidade do Rails com o poder de um banco de dados de classe mundial. O DB2, com seus vários recursos poderosos, incluindo armazenamento nativo em XML (pureXML), está liderando o caminho em termos de tornar os aplicativos Rails escaláveis no nível corporativo. Além disso, o DB2 pode fazê-lo a um preço imbatível, graças à versão absolutamente gratuita, o DB2 Express-C.

Recursos

Aprender

Obter produtos e tecnologias

  • DB2 Express-C: Faça o download do DB2 Express-C, um produto inteiramente licenciado disponível gratuitamente para a comunidade.
  • IBM Data Studio: Faça o download do IBM Data Studio:
  • Elabore seu próximo projeto de desenvolvimento com o software de teste IBM, disponível para download diretamente no developerWorks.

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Information Management, Software livre
ArticleID=468863
ArticleTitle=Melhore a segurança e o desempenho de aplicativos DB2 Ruby on Rails usando consultas parametrizadas
publish-date=03052010