Páginas

segunda-feira, 31 de dezembro de 2012

Proteja seu Sistema Contra: Quebra de Senha por Força Bruta



Esse artigo inicia uma série de artigos que mostrarão como podemos tornar nossos sistemas mais seguros contra ataques.

Hoje em dia é fácil obter conhecimento sobre como se tornar um hacker e atacar sites. Existe muito material na internet que ensina como atacar, quais as ferramentas a serem usadas etc. Como desenvolvedores não podemos simplesmente achar que nossos sistemas web nunca sofrerão ataques. Devemos estar preparados para repelir as principais técnicas utilizadas pelos hackers. Uma dessas técnicas é a quebra de senha por força bruta. Nesse tipo de ataque o hacker utiliza uma ferramenta que irá fazer várias combinações de caracteres até achar a senha correta. Essas combinações não são necessariamente aleatórias, mas usualmente são provenientes de uma lista de combinações pré-estabelecidas. Por exemplo, essa lista poderia conter as seguintes senhas:


'123456' (Essa é clássica!)
'adm'
'adm123'
'root'

Existem listas imensas contendo as senha mais utilizadas já disponíveis na internet para pronto uso pelos hackers. Como se precaver contra esse tipo de ataque?

Uma maneira é usando Captcha. Captcha é um mecanismo que inibe o acesso automatizado a determinada função que exija autenticação. Um exemplo clássico é a página de login dos sites que desenvolvemos. Um hacker pode entrar na página de login de um sistema e visualizar o código fonte. Vamos ver um exemplo de código:

<form action=”autenticar.php” method=”post”>
Usuário: <input type=”text” name=”usuario”/><br/>
Senha: <input type=”text” name=”senha”/><br/>
<input type=”submit” value=”Logar”/>
</form>

Visualizando o código fonte da página o hacker pode obter as informações necessárias para o seu ataque, são elas: a url do script que receberá a tentativa de login e os nomes dos campos. Esses parâmetros podem ser configurados em sua ferramenta de força bruta viabilizando assim sucessivos ataques.

O uso de captcha faz com que o script receptor não aceite acessos automatizados vindo de ferramentas, mas somente acessos legítimos de humanos. Pode-se conseguir isso por fazer uma pergunta aleatória na página de login que somente um humano pode responder e então verificar se a resposta dada foi a correta. Usualmente exibe-se ao usuário um conjunto aleatório de caracteres em uma imagem e então se pergunta a ele quais caracteres são estes.

Implementação: 
Quando a página de login é solicitada, crie uma sequencia de caracteres aleatórios, guarde essa sequencia na sessão, faça uma imagem contendo esses caracteres e exiba na página de login. Então no script que recebe a tentativa de login verifique se a sequencia de caracteres informado pelo usuário é igual a que está guardada na sessão.

Veja uma implementação em PHP:

Arquivo captcha.php

<?php
session_start();
header("Content-type: image/jpeg"); 
function captcha($largura, $altura, $tamanho_fonte, $quantidade_letras) {
    $imagem = imagecreate($largura, $altura);
    // COLOQUE ESTE ARQUIVO:  Comic_Sans_MS_Bold.ttf NA PASTA DESTE SCRIPT. PODE SER OUTRA FONTE
    $fonte = "Comic_Sans_MS_Bold.ttf"; 
    $preto = imagecolorallocate($imagem, 0, 0, 0);
    $branco = imagecolorallocate($imagem, 255, 255, 255);   
    $palavra = substr(str_shuffle("AaBbCcDdEeFfGgHhIiJjKkLlMmNnPpQqRrSsTtUuVvYyXxWwZz23456789"), 0, ($quantidade_letras));
   //COLOCA CAPCHA GERADO NA CESSÃO, DEPOIS SÓ CHAMAR $_SESSION["palavra"] PARA OBTER O CAPTCHA
    $_SESSION["palavra"] = $palavra;
    for ($i = 1; $i <= $quantidade_letras; $i++) {
        imagettftext($imagem, $tamanho_fonte, rand(-25, 25), ($tamanho_fonte * $i), ($tamanho_fonte + 10), $branco, $fonte, substr($palavra, ($i - 1), 1)); 
    }
    imagejpeg($imagem); 
    imagedestroy($imagem);
}

//ALTERE ESSES PARAMETROS DE ACORDO COM SEU GOSTO
$largura = 180;
$altura = 60;
$tamanho_fonte = 30;
$quantidade_letras = 5;

//GERA O CAPTCHA
captcha($largura, $altura, $tamanho_fonte, $quantidade_letras);
?>

Então altere seu formulário de login para:

<form action=”autenticar.php” method=”post”>
Usuário: <input type=”text” name=”usuario”/><br/>
Senha: <input type=”text” name=”senha”/><br/>
Digite os caracteres abaixo: <br/>
<img scr=”captcha.php”/><br/>
<input type=”text” name=”captcha”/><br/>
<input type=”submit” value=”Logar”/>
</form>

Exemplos de captchas gerados com <img src=”captcha.php” />:





Então na página autenticar.php basta verificar se o valor informado pelo usuário no campo captcha é igual ao captcha guardado na sessão. Isso praticamente inviabiliza tentativas automatizadas de login por ferramentas de hackers. No próximo artigo dessa série abordarei o ataque XSS e como podemos nos defender dele.

Atenciosamente,
Gustavo Marques

quinta-feira, 27 de dezembro de 2012

Colocando widget do twitter no seu sistema web





Colocar uma timeline qualquer do twitter no seu sistema web é bem simples. Existem algumas bibliotecas tanto em Java quanto em PHP. Porém uma ainda mais simples é a Twimg, disponível para implantação via  javascript. Se sua intenção é exibir uma timeline, ela é perfeita. Permite configurações nas cores, tamanho e muitas outras opções.

Vamos ao código:

<!-- Importe a biblioteca-->

<script src="http://widgets.twimg.com/j/2/widget.js"></script>


<!-- Instancie o objeto passando como parâmetro as opções, mude-as de acordo com seu gosto-->

<script>
new TWTR.Widget({
  version: 2,
  type: 'profile',
  rpp: 4,
  interval: 6000,
  width: 'auto',
  height: 300,
  theme: {
    shell: {
      background: '#9FB6FC',
      color: '#ffffff'
    },
    tweets: {
      background: '#fff2ff',
      color: '#545454',
      links: '#0781eb'
    }
  },
  features: {
    scrollbar: false,
    loop: false,
    live: true,
    hashtags: true,
    timestamp: true,
    avatars: false,
    behavior: 'all'
  }
}).render().setUser('programadorprof').start();
</script>

Perceba que na ultima linha 'render().setUser('programadorprof').start();' você passa como parâmetro o nome do usuário do twitter cuja timeline deseja exibir.

O resultado do código acima fica assim:




Atenciosamente,
Gustavo Marques

domingo, 23 de dezembro de 2012

Front Controller e Command com PHP

No post anterior introduzi os padrões Front Controller e Command. Expliquei seus benefícios e dei exemplos de como implementar em java. Nesse post apresentarei a versão em PHP (PHP versão 5 ou superior).

Leia o post original para entender os conceitos do artigo.

Vamos lá:

Estrutura de diretórios

./commands/
./commands/DeletarProduto.php
./commands/AlterarProduto.php
./Controller.php

DeletarProduto.php

<?php
class DeletarProduto{
    public function execute() {
         //DELETA O PRODUTO
    }     
}
?>

AlterarProduto.php

<?php
class AlterarProduto{
    public function execute() {
         //ALTERA O PRODUTO
    }     
}
?>

E agora o Controller.php:

<?php
//carrega o command
require_once "commands/".$_REQUEST['command'].".php";
$reflectionClass = new ReflectionClass($_REQUEST['command']);
$command = $reflectionClass->newInstance();
$command->execute();
?>

Para acessar o command basta usar a url: Controller.php?command=AlterarProduto ou Controller.php?command=DeletarProduto.

O Fato do PHP ter tipagem dinâmica facilita muito as coisas, tornando o código bem menos verboso em comparação com o java.

Atenciosamente,
Gustavo Marques

Ganhe Reusabilidade com Front Controller e Padronização com Command




No post anterior introduzimos os padrões de projetos. Neste post explicaremos dois deles: Front Controller e Command.

O padrão Front Controller é a base de muitos frameworks que conhecemos. Trata-se de uma maneira de centralizar os acessos em um único ponto e então, a partir deste,  rotear para uma ação (ou comando). Isso tem algumas vantagens. Em todas as aplicações existem funcionalidades que devem ser executadas em todos os acessos. Por exemplo verificar se o usuário está logado, verificar permissões e registrar log de acesso. São funções que devem ser executadas não importa qual a funcionalidade acessada. 

Vamos imaginar um cenário sem o front controller com command para entendermos a necessidade de sua implantação em nossos sistemas:

Certa aplicação em java possui 2 Servlets. Um para atualizar um produto e outro para deletar um produto. Em ambas as ações o usuário precisa estar logado, também é preciso registrar um log de acesso.

O primeiro Servlet foi escrito assim:

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AlterarProduto extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //PROCEDE COM A ALTERAÇÃO DO PRODUTO
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

E o segundo foi escrito assim:

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DeletarProduto extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //PROCEDE COM A EXCLUSÃO DO PRODUTO
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}


Há uma duplicação de código referente a verificação do usuário logado e o registro de log. E se precisarmos mudar algum código referentes a essas funcionalidades? teríamos que mudar todos os servlets. E se precisarmos adicionar mais alguma funcionalidade comum a todos os servlets? novamente teremos que alterar todos. Esse é um dos problemas que o front controller resolve.

Vamos ver como poderia ficar o nosso controller:

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Controller extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //ENCAMINHA PARA  AÇÃO (OU COMANDO) ESPECIALIZADO
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

Nesse modelo, as requisições 'alterar produto' e 'excluir produto' serão feitas ao mesmo servlet: Controller. Então o Controller depois de executar as funcionalidades comum as duas requisições irá encaminhar a solicitação a uma classe especializada. É aí que entra o padrão command. Quem não se lembra das famosas Actions do struts? Isso é o padrão command. Vamos implementar:

Crie uma interface Command

public inerface Command{
   public void execute(HttpServletRequest request, HttpServletResponse response);
}

Agora crie um pacote chamado 'commands' que irá conter seus commands.

Em seguida, vamos criar nossas implementações de Command:

package commands;
//imports
public class AlterarProduto implements Command{
   public String execute(HttpServletRequest request, HttpServletResponse response){
      //ALTERA O PRODUTO      
   }
}

package commands;
//imports
public class DeletarProduto implements Command{
   public String execute(HttpServletRequest request, HttpServletResponse response){
      //DELETA O PRODUTO      
   }
}

Agora vamos alterar o nosso Controller para reconhecer esses commands. Ele deve ser acessado pela seguinte url: Controller?command=AlterarProduto ou Controller?command=DeletarProduto. O parametro command é o nome da classe dos commands que implementamos. Se for necessário incluir um terceiro command 'CadastrarProduto' basta passar o nome nesse parametro e criar a classe que implementa Command no pacote commands.

Segue o controller

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Controller extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //EXECUTA O COMANDO ESPECIFICADO NA URL
        Command comando = (Command)Class.forName("commands."+request.getParameter("command")).newInstance();
        comando.execute();        
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

Percebam que na instanciação do command e passo o nome da classe informada pela url. Aqui podemos visualizar o motivo do padrão command facilitar a padronização. Visto que todos os commands implementam a interface Command podemos usar o polimorfismo e instanciar várias implementações diferentes. Isso permite que nossa aplicação cresça sem a necessidade de alterar o nosso controller ou o nosso web.xml por adicionar novos servlets.

O foco deste artigo foi explicar e demonstrar os padrões front controller e command. Naturalente existem maneiras mais bem elaboradas para implementar, usando por exemplo DI e annotations. Porém desta maneira os conceitos são apresentados sem perder o foco.

Num próximo artigo apresentarei os padrões front controller e command implementados em PHP.

Atenciosamente,
Gustavo Marques

quinta-feira, 20 de dezembro de 2012

Gerando relatórios em PDF com PHP

É interessante que algumas das consultas que nossas aplicações fazem ao banco de dados pudessem ser exportadas em PDF para o usuário poder baixar a partir de seu navegador. Como implementar isso em PHP? Podemos utilizar a Classe FPDF.

Instalação:
Baixe a Classe FPDF. http://www.fpdf.org/

Quando extrair o conteúdo do arquivo baixado, coloque em seu projeto apenas o arquivo fpdf.php e a pasta font. Pronto! Sua aplicação já está preparada para criar relatórios em PDF.

Utilização:
Para utilizar a biblioteca é muito simples. Primeiro busque no banco de dados os registros que deseja exportar na forma de um array (poderá ser um array bidimencional ou um array de objetos) e depois utilize os métodos providos pela classe fpdf para gerar se PDF.

Vamos ao código:


<?php
require_once 'dominio/Pessoa.php';// nesse caso será um array de objetos Pessoa
require_once 'dao/PessoaDAO.php';
require_once 'fpdf.php';

//OBTENDO DADOS DO BANCO
$dao = new PessoaDAO();
$data = $dao->listarPessoas();

//CRIA A PÁGINA EM PDF
$pdf = new FPDF();
$pdf->AddPage('P', 'A4');

//CABEÇALHO DO RELATÓRIO
//Coloque aqui uma imagem como logo no seu relatório
//Se não precisar de imagem, apague essa linha
$pdf->Image('images/logo.png', -20);
$pdf->SetFont('Arial', 'B', 15);
$pdf->Cell(80);
$pdf->Cell(30, 10, 'Pessoas', 0, 0, 'C');//'Pessoas' centralizado no meio da página
$pdf->Ln(20);

//CABEÇALHO DA TABELA
$pdf->SetFont('Arial', 'B', 11);
$pdf->Cell(90, 7, 'Nome', 1);
$pdf->Cell(90, 7, 'Email', 1);
$pdf->Ln();

//POPULANDO A TABELA
$pdf->SetFont('Arial', '', 11);
foreach ($data as $row) {
    $pdf->Cell(90, 6, $row->getNome(), 1);
    $pdf->Cell(90, 6, $row->getEmail(), 1);
    $pdf->Ln();
}

//FORÇA O DOWNLOAD PELO BROWSER
$pdf->Output('pessoas.pdf', 'D');
?>


Veja abaixo um exemplo de como fica o PDF gerado:





Atenciosamente,
Gustavo Marques

quarta-feira, 28 de novembro de 2012

Porque vale a pena estudar e utilizar padrões de projeto?



        Sente-se desanimado em meio a tantas siglas e palavras desconhecidas? Talvez ache que programador tem que colocar logo a mão na massa (ou no teclado) e sair programando. Porque então dedicar tempo para estudar padrões de projeto?
   
        Vale muito a pena estudar padrões de projeto. Todos nós nos beneficiamos dos padrões em diversas áreas da vida. Pense por exemplo no corpo humano: o que aconteceria se cada indivíduo tivesse seus órgãos internos em um local diferente do corpo? Quanto trabalho daria ao cirurgião localizar primeiro onde se encontra tal órgão, entender suas particularidades para então começar uma cirurgia? Felizmente nossos corpos seguem um padrão, duas pernas, dois olhos, coração localizado no peito etc. E isso facilita sua 'manutenção'. Essa metáfora pode ser aplicada ao desenvolvimento de software. O uso de padrões de desenvolvimento trás uma série de benefícios.

      Ainda não se convenceu com a metáfora acima de que é benéfico o uso de padrões? Então vamos utilizar outra metáfora: Imagine se alguém lhe pedisse para construir um automóvel do zero. Mesmo de posse das peças certas, é provável que leve vários anos para conseguir. E uma vez terminado, o produto final talvez não colabore para uma manutenção por terceiros. Agora se você visitasse primeiro uma linha de produção de uma montadora de automóveis, veria como cada peça é encaixada, qual o lugar de cada uma no conjunto etc. Ou seja, alguém já gastou um bom tempo entendendo funcionamento correto de um automóvel, onde cada peça deve ficar, como encaixá-las, e tornou esse conhecimento disponível para a montadora construir automóveis da maneira certa, segura e ágil. Isso se aplica ao desenvolvimento de software. Muitos já construíram software da maneira errada e aprenderam lições disso. Outros construíram software da maneira correta e observaram os benefícios resultantes. Esse conjunto de experiências proporcionam um excelente conhecimento disponível. Podemos dizer que utilizar padrões de projeto é se beneficiar da experiência adquirida por outros.

        Se convenceu de que vale a pena estudar e utilizar padrões de projeto?

       Em próximos posts falarei de alguns padrões de projeto que devem estar em todos os projetos: DAO, MVC, Factory. Também explicarei outros que irão trazer ainda mais benefícios, como o Command, Front Controller e DI (Injeção de Dependências).



       Gustavo Marques.

sábado, 17 de novembro de 2012

Tratando vários campos checkbox de mesmo nome com PHP

Em nossos formulários podemos ter uma lista de itens a serem selecionados pelo usuario. Esses campos podem ter o mesmo nome e devem ser recebidos na forma de array no script receptor. Isso é interessante pois se forem muitos itens ou de tamanho desconhecido (geralmente quando vem do banco) fica inviável ler campo a campo no PHP.
Veja como implementar:

Primeiramente o form:

<form action="gravar.php" method="post">
   <input type="checkbox" name="itens[]" value="1" /> Item 1<br/>
   <input type="checkbox" name="itens[]" value="2" /> Item 2<br/>
   <input type="checkbox" name="itens[]" value="3" /> Item 3<br/>
   <input type="submit" value="Enviar" /> 
</form>

Perceba que o nome deve ser terminado com '[]', para instruir o PHP de que se trata de um array.
O script:

<?php
$itens= $_REQUEST['itens'];

if (!empty($itens)) {                
      $qtd = count($itens);
       for ($i = 0; $i < $qtd; $i++) {
            echo $itens[$i];//imprime o item corrente
       }
 }

?>

Com esse código você pode ter uma lista de 1000 checkbox que não faz diferença, não precisará ler um a um.


Gustavo Marques.

Validando, gravando e lendo campos tipo Date no padrão 'dd/mm/aaaa' com PHP + Mysql

Nossos formulários podem conter campos tipo date, tais como a data de nascimento. É interessante que guardemos essa informação no banco de dados com o tipo correto. Isso nos permite fazer operações de data com essa data guardada, por exemplo, buscar os usuários que possuem certa idade.

Crie a tabela no banco:

CREATE TABLE  `usuario`(
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `nome` text NOT NULL,
   `nascimento` date NOT NULL,
   PRIMARY KEY (`id`)
)


Crie o formulário HTML:

Novo usuario:<br/>
<form action="gravar.php" method="post">
<input type="text" name="nome" /><br/>
<input type="text" name="nascimento" /> (dd/mm/aaaa)<br/>
<input type="submit" value="gravar" />
</form>

Perceba que a data a ser fornecida tem que seguir o padrão 'dd/mm/aaaa'

Crie o script gravar.php que guardará no banco (coloco o script de forma simplificada para não perder o foco do artigo, mas o ideal seria isolar o código que acessa o banco de dados em um objeto DAO)


<?php

//função que valida a data

function dataValida($dat) {
        try {
            $data = explode("/", $dat); // explode a string $dat em pedaços, usando / como referência
            $d = $data[0];
            $m = $data[1];
            $y = $data[2];

            // verifica se a data é válida!
            // 1 = true (válida)
            // 0 = false (inválida)
            $res = checkdate($m, $d, $y);
            if ($res == 1) {
                return true;
            } else {
                return false;
            }
        } catch (Exception $exc) {
            return false;
        }
    }


$furou = false;//controla a validação

if (trim($_REQUEST['nascimento']) == '' || !dataValida($_REQUEST['nascimento'])) {
            $furou = true;
}

if (trim($_REQUEST['nome']) == '') {
            $furou = true;
}
if($furou){
   echo 'Todos os campos são obrigatórios! Verifique o formato da data dd/mm/aaaa';
   //redirecione de volta para o formulário
}else{
   //ok, pode gravar
   $connection = mysql_connect('bancourl', 'usuario', 'senha');        
   $db = mysql_select_db($config->getDataBaseName(), $connection);        
   $sql = "insert into usuario(nome, nascimento) values ('".$_REQUEST['nome'])."', STR_TO_DATE('" . $_REQUEST['nascimento']) . "','%d/%m/%Y'))";
   mysql_query($sql);  
   echo mysql_error();
   mysql_close($connection);
}


?>

Observe que oriento o MySQL a usar o padrão 'dd/mm/aaaa' nesse trecho: '%d/%m/%Y'. Você pode alterar essa padrão por exemplo para dd-mm-aaaa usando: '%d-%m-%Y', mas lembre de alterar também a função em php onde fazemos a validação da data.

Para exibir a data cadastrada:


$connection = mysql_connect('bancourl', 'usuario', 'senha');        
   $db = mysql_select_db($config->getDataBaseName(), $connection);        
   $sql = "select nome, DATE_FORMAT(nascimento,'%d/%m/%Y') as nascimento from usuario";
   $result = mysql_query($sql);  
   while ($row = mysql_fetch_array($result)) {
      echo $row['nascimento'];// exibirá a data no formato dd/mm/aaaa
   }
   echo mysql_error();
   mysql_close($connection);



Fica a dica.

Gustavo Marques.

Gerando senhas aleatórias com PHP

Um sistema que possua uma base de usuários com login e senha precisa fornecer mecanismos para recuperação de senha. Isso é importante porque o usuário pode esquecer sua senha. Assim é comum encontrarmos o link 'esqueci minha senha' nos sistemas que possuem login.
Ao clicar nesse link podemos gerar uma senha randômica e enviá-la por email ao usuário.

Essa solução tem várias implementações, segue uma maneira

function gerarNovaSenha(){
   $letras = array(
            'a',
            'b',
            'c',
            'd',
            'e',
            'f',
            'g',
            'h',
            'i',
            'j',
            'k',
            'l',
            'm',
            'n',
            'o',
            'p',
            'q',
            'r',
            's',
            't',
            'u',
            'v',
            'x',
            'z',
            '0',
            '1',
            '2',
            '3',
            '4',
            '5',
            '6',
            '7',
            '8',
            '9'
        );
        shuffle($letras);       
        $novasenha = '';
        for ($i = 0; $i < 10; $i++) {//10 é o tamanho da nova senha, substitua conforme a necessidade
            $novasenha = $novasenha . $letras[$i];           
        }
        return $novasenha;
}

Poderá incluir ainda nesse array simbolos '#@*&-_=+' e também caracteres em maiúscula para diversificar ainda mais.

Gustavo Marques.

quarta-feira, 7 de novembro de 2012

CRUD no Banco de Dados com Java e JDBC parte 2 - Criando seu Servlet

No post anterior expliquei como criar o seu DAO, ou seja, a camada de sua aplicação que irá acessar o banco de dados.

Vamos agora criar o nosso Servlet que irá utilizar os serviços oferecidos pelo nosso DAO.

Servlet

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package servlets;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author User
 */
public class ListarProdutos extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //variável que controla para qual view rotear após a execução desse Servlet
        String view = "";
        //Vamos criar uma conexão com o banco de Dados para passar ao nosso Dao.
        //É esse servlet que irá gerenciar a conexão
        java.sql.Connection con = null;
        try {
            con = Conexao.fabricar();//padrão factory, classe descrita depois desse servlet.
            con.setAutoCommit(false);//permitindo transações
            ProdutoDao dao = new ProdutoDao(con);
            List<Produto> produtos = dao.listarTodos();
            con.commit();
            //manda para a view
            request.setAttribute("produtos",produtos);
            view = "listagem.jsp";
        } catch(Exception ex){
            view = "erro.jsp";
            try{
               con.rollback();
           }catch(Exception ex2){}
        }finally {            
            try{
               con.close();
           }catch(Exception ex3){}
        }
        request.getRequestDispatcher(view).foward(request, response);
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}

Não esqueça de registrar seu Servlet no arquivo web.xml, logo abaixo da tag <web-app> inclua:

web.xml


   <servlet>
        <servlet-name>ListarProdutos</servlet-name>
        <servlet-class>servlets.ListarProdutos</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ListarProdutos</servlet-name>
        <url-pattern>/ListarProdutos</url-pattern>
    </servlet-mapping>

Agora a classe Fábrica de Conexões:

Conexao.java

public class Conexao {

    public static Connection fabricar() throws Exception {       
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        return DriverManager.getConnection("jdbc:mysql://localhost/banco" ,"usuario" ,"senha" );
    }
}

No próximo post implementaremos a View com JSP e JSTL.

Gustavo Marques.

segunda-feira, 5 de novembro de 2012

Fazendo download de arquivos pelo navegador com java a partir de sua aplicação web

Muitas são as situações que exigem a implementação de download de arquivo. Podemos gerar um relatorio em pdf dinamicamente e disponibiliza-lo para download pelo navegador, ou baixar imagens, arquivos zip etc. Porém as vezes não podemos simplesmente passar o caminho do arquivo via url para o usuario digitar na barra de endereços. Um exemplo disso são .war magros. Os usuários vão fazendo uploads mas os arquivos não ficam em uma pasta do war, mas sim em uma pasta do servidor fora do contexto da aplicação, por exemplo C:\arquivos. Os usuarios do sistema web não podem acessar essa pasta do servidor pelo browser, pois está fora do contexto da aplicação.
Assim devemos criar um objeto java.io.File com a localizaçao do arquivo que queremos servir e escrevê-lo no HttpServletResponse.

Vamos ao código:

File arquivo = new File("C:\arquivos\relatorio.pdf");

//tipo de arquivo
response.setContentType("application/pdf");

//nome do arquivo a ser exibido na caixa de download do browser
response.setHeader("Content-Disposition", "attachment; filename=" + arquivo.getName()+ ";");

//manda os bytes do arquivo pelo response
URL url = arquivo.toURI().toURL();
BufferedInputStream leitor = new BufferedInputStream(url.openStream(), 4 * 1024);
OutputStream escritor = response.getOutputStream();
byte[] buffer = new byte[4 * 1024];
int size = 0;
while ((size = leitor.read(buffer, 0, buffer.length)) != -1) {
   escritor.write(buffer, 0, size);
}
escritor.close();
leitor.close();

Isso fará com que o browser do usuário exiba a caixa de download.

Se você não souber antecipadamente qual o tipo de arquivo que irá entregar, poderá definir em tempo de execução verificando a extensão do arquivo:


//pega a extensão do arquivo
String[] partes = arquivo.getNome().split("\\.");
int ultimaParte = partes.length - 1;
String extensao = partes[ultimaParte];

//seta o content type segundo a extensão
if (extensao.equals("doc")) {
   response.setContentType("application/msword");
}
if (extensao.equals("pdf")) {
   response.setContentType("application/pdf");
}
if (extensao.equals("pdf")) {
   response.setContentType("application/pdf");
}
if (extensao.equals("xls")) {
   response.setContentType("application/vnd.ms-excel");
}
if (extensao.equals("ppt")) {
   response.setContentType("application/vnd.ms-powerpoint");
}
if (extensao.equals("gzip")) {
   response.setContentType("application/gzip");
}
if (extensao.equals("zip")) {
   response.setContentType("application/zip");
}
if (extensao.equals("au") || extensao.equals("snd")) {
   response.setContentType("audio/basic");
}
if (extensao.equals("midi")) {
   response.setContentType("audio/midi");
}
if (extensao.equals("aiff")) {
   response.setContentType("audio/x-aiff");
}
if (extensao.equals("wav")) {
   response.setContentType("audio/x-wav");
}
if (extensao.equals("gif")) {
   response.setContentType("image/gif");
}
if (extensao.equals("jpg") || extensao.equals("jpeg")) {
   response.setContentType("image/jpeg");
}
if (extensao.equals("png")) {
   response.setContentType("image/png");
}
if (extensao.equals("tiff")) {
   response.setContentType("audio/tiff");
}
if (extensao.equals("bmp")) {
   response.setContentType("image/x-xbitmap");
}
if (extensao.equals("html") || extensao.equals("htm")) {
   response.setContentType("text/html");
}
if (extensao.equals("txt")) {
   response.setContentType("text/plain");
}
if (extensao.equals("xml")) {
   response.setContentType("text/xml");
}
if (extensao.equals("mpeg")) {
   response.setContentType("video/mpeg");
}


Gustavo Marques.

quinta-feira, 1 de novembro de 2012

Criando jogos em HTML 5 utilizando canvas

O html5, principalmente com a funcionalidade de canvas, possibilita a criação de jogos interessantes.
Nesse post mostrarei um exemplo breve de um jogo feito em html 5.
Nesse jogo controlaremos uma nave viajando pelo espaço.

Primeiro precisaremos de 2 imagens: Uma da nave e outra do espaço.
Nesse post eu expliquei como gerar imagens 2d por meio do blender. Vou usar uma como exemplo.



É importante que ela possua fundo transparente (.png).

Agora precisamos da imagem background:



Com essas duas imagens a disposição, já podemos programar nosso jogo.

Vamos ao código.
Para não ter um código sujo, vamos separar o html do javascript em arquivos separados.

jogo.html


<html>
    <head>
        <title>Jogo</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
    </head>
    <body>
    <center>
        <h1>Meu Primeiro jogo em html 5</h1>
        <br/>

<br/>
        <canvas id="game" width="500" height="500" style="border: 1px solid #000000;">
            <p>Seu navegador não suporta HTML5!</p>
        </canvas>
        <script src="codigo.js"></script>     
    </center>
</body>
</html>


Nesse código temos o elemento <canvas> onde desenharemos com javascript. Agora vamos ao arquivo codigo.js

codigo.js


// cria o contexto grafico no canvas
var drawingCanvas = document.getElementById('game');
var ctx = drawingCanvas.getContext('2d');

var framecount = 0;


// carrega imagens
// Criando Background e seus objetos
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
    bgReady = true;
};

bgImage.src = 'bg.jpg';

var naveReady = false;
var naveImage = new Image();
naveImage.onload = function () {
    naveReady = true;
};
naveImage.src = 'nave.png';

//objetos do jogo
var nave = {
    speed:256,
    x:220,
    y:440,
    w:60,
    h:60,
    currentImage:null
};


//teclado
var keysDown = {};
addEventListener('keydown', function (e) {
    keysDown[e.keyCode] = true;
}, false);
addEventListener('keyup', function (e) {
    delete keysDown[e.keyCode];
}, false);


// frame update
var update = function(modifier){
    if (38 in keysDown) { // Jogador vai para cima
        //verifica se já está no limite
        if(nave.y >= 0){
            nave.y -= nave.speed * modifier;          
        }
    }
    if (40 in keysDown) { // Jogador vai para baixo
        if(nave.y <= 500-nave.h){
            nave.y += nave.speed * modifier;          
        }
    }
    if (37 in keysDown) { // Jogador vai para esquerda
        if(nave.x >= 0){
            nave.x -= nave.speed * modifier;          
        }
    }
    if (39 in keysDown) { // Jogador vai para direita
        if(nave.x <= 500 - nave.w){
            nave.x += nave.speed * modifier;          
        }
    }




    framecount++;
}

//render game
var render = function(){
    //clear no canvas
    //ctx.fillStyle = 'rgb(1, 1, 1)';
    //ctx.fillRect(0, 0, 500, 500);
 
    if (bgReady) {
        ctx.drawImage(bgImage, 0, 0);
    }
    if (naveReady) {
        ctx.drawImage(naveImage, nave.x, nave.y);
    }
    // pinta o framecount
    ctx.fillStyle = 'rgb(250, 250, 250)';
    ctx.font = '10px Verdana';
    ctx.textAlign = 'left';
    ctx.textBaseline = 'top';
    ctx.fillText('Frame: ' + framecount, 390, 480);

}

//função que irá controlar o game loop
var main = function () {
    var now = Date.now();
    var delta = now - then;
    update(delta / 1000);
    render();
    then = now;
};

//iniciando o game
var then = Date.now();
setInterval(main, 1);


Não se assuste! Leia os comentários que está bem claro. Veja as explicações abaixo na ordem dos comentários:

1- Iniciamos o contexto do canvas.

2- Carregamos as imagens do jogo. Observe que coloquei 2 variáveis booleanas para saber quando as imagens foram carregadas e assim poder pintalas no canvas.

3- Criamos o objeto nave (sprite) com as propriedades de localização no canvas e suas dimensões.

4- Registramos as teclas pressionadas.

5- Entramos agora na função update. Ela será executada a cada frame. Se você não entende esse conceito de frame e game loop leia esse post. Dentro da função update atualizamos a posição da nave, verificando sempre se ela já atingiu o limite do cenário. A variavel framecont eu adicionei só para vocês observarem que durante um jogo o game loop acontece. Ela vai sendo incrementada e exibida a cada frame.

6- A função render é responsável por pintar na tela o estado atual do jogo, nesse caso a posição atual da nave. Observe que pintamos utilizando os métodos de ctx. Ele funciona como o graphics do java 2d.

7- A função main é o game loop. Ela será executada no intervalo definido na ultima linha setInterval();


Gustavo Marques

terça-feira, 30 de outubro de 2012

Inserindo conteúdo dinâmico com JQuery

A biblioteca jquery facilita muito o trabalho em tornar nossas interfaces mais interativas.
Nesse exemplo mostrarei como adicionar conteúdo dinamicamente na página.

Essa funcionalidade é importante em várias situações, como adicionar novos itens, novos campos para preenchimento etc.

Nesse exemplo vamos inserir novos campos de preenchimento de um cadastro

Vamos ao código:

<html>
   <head>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
   </head>
   <body>
      <input onclick="$('#conteudo').append('Novo Item: <input type=text /><br/>');" type="button" value="Adicione mais itens" />
      <div id="conteudo"></div>
   </body>
</html>

Testando o código:







O Evento onclick do input irá acionar o método append do jquery, esse método adiciona um conteudo dentro e ao final de um elemento.
Adapte esse exemplo a suas necessidades,

Gustavo Marques.


Veja mais detalhes
 

terça-feira, 16 de outubro de 2012

Como recortar um pedaço de uma imagem (crop) utilizando javascript e PHP

Muitos sistemas precisam guardar as fotos de seus usuários. O problema é que o usuário final raramente terá uma foto nas dimensões adequadas (e mais dificilmente ainda ele abrirá a imagem disponível em um software grafico para dar um resize), de modo que é interessante oferecer a funcionalidade de crop na foto que subiu via upload. Crop significa recortar um pedaço da imagem.

Recentemente em um projeto tive que implementar essa função.

Segue os prints:

Step 1: O usuario seleciona uma foto qualquer em seu computador

Step 2: O usuário é redirecionado para a página de recorte (crop) da imagem que ele enviou

Step 3: O pedaço da imagem que ele recortou será usado para representá-lo no sistema.


Vamos ao código:

Primeiro vamos precisar de uma lib javascript que faz crop, tem várias.
A que eu escolhi é esta aqui: http://uvumitools.com/crop.html
Pegue todos os arquivos e coloque em seu projeto

Crie uma página PHP com um formulário para o upload da imagem:

<form action="upload.php?user_id=2353" enctype="multipart/form-data" method="POST">
<input id="fileInput" name="arquivos" type="file" />
<input type="submit" value="Salvar Foto" />
</form>

Agora crie o arquivo upload.php que irá receber esse upload vindo do form:

$destino = 'C:\xampp\htdocs\site\uploads';//estou usando a pasta uploads para guardar os arquivos
if (!$_FILES) {
    echo 'Nenhum arquivo enviado!';
} else {
    $file_name = $_FILES['arquivos']['name'];
    $file_type = $_FILES['arquivos']['type'];
    $file_size = $_FILES['arquivos']['size'];
    $file_tmp_name = $_FILES['arquivos']['tmp_name'];
    $error = $_FILES['arquivos']['error'];
}

switch ($error) {
    case 0:
        break;
    case 1:
        echo 'Tamanho do arquivo ultrapassou o limite';
        break;
    case 2:
        echo 'O tamanho do arquivo é maior do que o permitido!';
        break;
    case 3:
        echo 'O upload não foi concluí­do!';
        break;
    case 4:
        echo 'O upload não foi feito!';
        break;
}

if ($error == 0) {
    if (!is_uploaded_file($file_tmp_name)) {
        echo 'Erro ao processar arquivo!';
    } else {
//concateno o time no nome do arquivo para evitar sobrescrever arquivos de mesmo nome
        $time = time();
        if (!move_uploaded_file($file_tmp_name, $destino . "/" . $time.$file_name)) {
            echo 'Não foi possível salvar o arquivo!';
        } else {
            //vai para o crop
            require_once 'crop_editor.php';//carrega aqui a página que faz o crop
        }
    }
}

O arquivo crop_editor.php:
Certifique-se de que esses arquivos js e css estejam nos locais apropriados.

<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
        <script src="js/mootools-for-crop.js" type="text/javascript"> </script>
        <script src="js/UvumiCrop-compressed.js" type="text/javascript"> </script>
        <link href="css/uvumi-crop.css" media="screen" rel="stylesheet" type="text/css"></link>
     
        <style type="text/css">
            body,html{
                background-color:#333;
                margin:0;
                padding:0;
                font-family:Trebuchet MS, Helvetica, sans-serif;
            }

            hr{
                margin:20px 0;
            }

            #main{
                margin:5%;
                position:relative;
                overflow:auto;
                color:#aaa;
                padding:20px;
                border:1px solid #888;
                background-color:#000;
                text-align:center;
            }

            #resize_coords{
                width:50px;
            }

            #previewExample3{
                margin:10px;
            }

            .yellowSelection{
                border: 2px dotted #FFB82F;
            }

            .blueMask{
                background-color:#00f;
                cursor:pointer;
            }
        </style>
        <script type="text/javascript">
            exampleCropper1 = new uvumiCropper('imagem',{
                coordinates:false,
                preview:true,
                downloadButton:false,
                saveButton:true,
                serverScriptSave:'crop_it.php',  //aqui a pagina que recebe os parametros do crop
                onCropSuccess:function(){
                    document.location = 'sucesso.php';
                },
             
                onCropFail:function(){
                    document.location = 'error.php';
                },
                mini:{
                    x:150,
                    y:150
                },
                parameters:{
                    usuario_id:'<?php echo $_REQUEST['user_id']?>'
                }
            });
        </script>
    </head>
    <body>
        <div>
            <img alt="cropping test" id="imagem" src="uploads/?php echo $time . $file_name;?" />
        </div>
<div id="saida">
</div>
</body>
</html>

Agora a página crop_it.php:


$h=$_REQUEST['height'];   
$x=$_REQUEST['left'];
$y=$_REQUEST['top'];
$filename=$_REQUEST['filename'];
header('Content-type: image/jpg');
//header('Content-Disposition: attachment; filename='.$src);
$image = imagecreatefromjpeg('uploads/'.$filename); 
$crop = imagecreatetruecolor($w,$h);
imagecopy ( $crop, $image, 0, 0, $x, $y, $w, $h );
imagejpeg($crop);


Pronto, aparecerá somente o pedaço escolhido.
Você pode fazer alterações nesse arquivo, como por exemplo salvar em disco o pedaço da imagem e associar o nome dessa nova imagem ao usuário no banco de dados. Repare que desde o formulário estou passando o id do usuario, você pode recuperá-lo aqui usando $_REQUEST['usuario_id'], ou pegar da sessão.

Espero que esse exemplo ajude.
atenciosamente,
Gustavo Marques.

Veja também

Related Posts Plugin for WordPress, Blogger...