COST do password_hash

Como complemento para o post Como armazenar as senhas corretamente com PHP, quero mostrar como o parâmetro “cost” é utilizado no password_hash e com isso te ajudar a entender qual é o valor mais adequado para você usar.

Um detalhe quanto ao valor do “cost”, não há um valor certo para a sua aplicação, você tem que escolher um valor que faça sentido para ela. Por isso esse post, ele é para explicar justamente o impacto que esse parâmetro tem.

Para saber o tempo que de cada valor do “cost” executei esse script.

E esse foi o resultado em segundos.

A configuração da máquina que estou usando é essa.

Com base nesses valores, você consegue ter uma base de quanto tempo vai levar para gerar uma senha, lembrando que sempre que um usuário se cadastrar, ou logar ela vai chamar os comandos de password várias vezes e isso vai impactar no tempo que ele leva para entrar em seu sistema e fora isso, vai sobrecarregar o seu servidor, então, outros usuários podem ser impactados com isso.

É isso.

Como armazenar as senhas corretamente com PHP

Garantir que as senhas dos usuários estão armazenadas corretamente no banco de dados da um certo trabalho, mas assim, ainda não é ciência de foguete, para você usar md5 porque é fácil. Vale lembrar que o md5 não serve para nada e bem no nível do NADA MESMO.

Muitas vezes, a validação de login fica como responsabilidade do banco de dados (Oi? Claro que não, ta louco!).

Quem não fez algo assim (favor ignorar o sql injection):

$sql = “SELECT id FROM user WHERE email=’$email’ AND password=MD5(‘$password’)”;

Você não valida depois se veio uma linha? Então, quem validou foi o banco…

Sendo desse jeito, não temos muito o que fazer. A primeira coisa que precisa ocorrer é alterar quem valida a senha do usuário e isso quem deve fazer é a aplicação.

Nesse contexto, vamos usar as funções de senhas do PHP.

password_hash

password_verify

Conforme manual, password_hash, vai gerar uma senha bem diferente do md5 e se fizer certinho não mexe mais (spoiler, explico no final).

Simples nesse nível:

Agora, o que é o que.

PASSWORD_DEFAULT

É uma constante do PHP que justamente gerencia qual será o algoritimo de criptografia. Ela será alterada caso em uma nova versão do PHP tenha uma forma melhor de criptografia.

cost

É o “custo” daquele hash, quanto maior o custo maior é o tempo para gerar uma senha (explicação prática do cost aqui). Por padrão o cost é 10, logo se eu não passase ele daria na mesma.

Blz, já salvei a senha do meu usuário e tudo mais, agora como eu valido isso?

Pois é, “tudo” isso.

Como bônus, agora vem a parte do corretamente.

O “password_needs_rehash” verifica se o hash usado como senha ainda é o melhor que há disponível.

Pense assim, hoje você esta usando o “cost” 10, mas amanhã vai começar a usar o 11, ou 12, ou o “PASSWORD_DEFAULT” mudou, quando que você vai alterar o hash da senha do usuário? Dessa forma, você já aproveita que você tem a senha do usuário e criptografa ela no novo padrão de hash.

Dessa forma, quando mudar o padrão de criptografia, ou quando você mudar a configuração do “cost” seu código já vai estar preparado para isso e o hash vai ser alterado para o mais novo.

Espero que isso ajude 🙂

Mão na massa – Integração contínua com FTP em hospedagem compartilhada

Dando continuidade ao post sobre integração contínua com FTP (Se não viu segue o link).

Vamos a como resolvi esse meu problema.

Não vou explicar sobre o Git, esse já tem sua documentação fácil.

Começando com o Bitbucket, ative o pipeline, em seu projeto Configurações > Pipelines > Settings (O Bitbucket ainda não fez toda a tradução)

Criei o arquivo bitbucket-pipelines.yml na raiz do projeto, ele é o responsável pela build. Um exemplo simples, apenas rodando o PHPUnit é esse:

Pronto, com isso a cada commit que for feito, o Bitbucket vai disparar a pipeline e com isso gerar o build, com isso vamos ter o seguinte resultado:

Com o processo de build e testes automatizado, podemos pensar no deploy. Para isso usei o DeployBot. Quando criamos o primeiro repositório, o DeployBot faz uma interface passo a passo, mas, como meu plano é o gratuito, só tenho um repositório e ele esta em uso. Vou mostrar as configurações, ai você pode ajustar 🙂

No primeiro passo, criamos o ambiente, no meu caso, apenas produção (no test no fear).

E suas configurações.

Com a configuração de deploy manual, eu preciso mandar fazer o deploy todas as vezes, se esse servidor fosse de QA, facilmente estaria no automático.

Depois de criar o ambiente, é necessário criar os servidores, essa parte é o simples apontamento para onde os arquivos de deploy devem ir.

Configuração de FTP.

No seu cPanel.

Agora que já sabe para onde vai, hora de ajustar as dependências

Outra coisa que podemos fazer aqui, é colocar arquivos com base no ambiente, isso ajuda nas configurações de banco de dados por exemplo.

Essa parte eu não consegui entender bem, mas, em meus testes, sem usar isso a próxima parte da problema…

Aqui ele simplesmente instancia o docker e executa “php -v”, só para saber a versão mesmo, sem segredo.
Essa é a parte da mágica, o DeployBot, só vai executar essa parte caso o composer.json seja alterado, isso é muito bom, pois não vai enviar a pasta vendor sem a necessidade

Agora é só partir para o deploy.

Quando você executa o deploy a primeira vez, ele vai enviar tudo (TUDO) e ficar mais ou menos assim.

Carregando as dependências.Enviando os arquivos.Quando precisar fazer outro deploy, vai enviar apenas a diferença.Aqui, você também pode ver o arquivo de configuração por ambiente foi enviado.

Agora é só curtir 🙂

Integração contínua com FTP em hospedagem compartilhada

Deploy via FTP hoje em dia é tipo o Batman, o herói que nós precisamos e não o que queremos.

Nos últimos dias, estou trabalhando em um projeto que não há orçamento disponível, basicamente, minha esposa mandou parar de gastar.

Junto com um amigo, tenho um plano de revenda de hospedagem compartilhada, esse aqui, vendemos esse serviço para outros amigos e por ai vai. Como não há orçamento para esse projeto, estou usando uma cota minha da revenda.

Sendo uma hospedagem compartilhada eu perco diversas coisas, uma delas é o acesso SSH, algumas até disponibilizam, mas a minha experiência com isso não foi das melhores.

Vamos ao ambiente. Como repositório de código eu deixo no Bitbucket, isso porque eu posso criar repositórios privados de graça. Com ele eu uso o serviço de pipeline, também de graça. No pipeline, posso montar da mesma forma como no Trevis CI, um arquivo de configurações e ele se vira para rodar os testes unitários, de aceitação e por ai vai.

O deploy, faço via FTP, sim é muito chato fazer isso, mas tem um cara que resolve esse problema para mim, novamente, DE GRAÇA, ele é o DeployBot, com ele, consigo rodar “composer install” em uma imagem docker e ele gerencia isso para mim, pega os arquivos criados na pasta vendor e encaminha para o servidor, conforme for alterado o composer.json ele vai enviar novamente essa pasta, caso contrário só vai enviar as alteraçõs que estão no commit, esse gerenciamento é o que possibilita o deploy via FTP ser aceitável.

Juntando tudo isso, eu consigo fazer meus deploys de forma fácil, não preciso deixar as dependências no projeto e o melhor, usar efetivamente um FTP, o DeployBot que se vire nisso.

Volto a falar, existem formas melhores de fazer isso, mas o deploy via FTP é uma realidade, vamos deixar isso pelo menos mais fácil.

Assim que terminar eu posto o mão na massa, explicando como eu fiz tudo.

 

[ATUALIZAÇÃO]

Link explicando como foi feito.

Code Review

Faça Code Review, do que? De tudo.

Quando? A cada pull request.

E se eu não uso pull request? Se o time tem mais pessoas comece a usar.

Sério? Não não, escrevi tudo isso para te sacanear. Claro que precisa

Ela não é apenas para Open Source, fica a dica.

Brincadeiras a parte, fazer a revisão do código é a melhor forma de espalhar o conhecimento dentro do time, além disso, melhor maneira para que todos saibam e sigam os padrões de desenvolvimento adotados.

Pense no código como uma criança, ela precisa crescer, precisa de liberdade para criar as suas próprias ideias, fora isso, precisa também de supervisão, de alguém mostrando o caminho certo. É nesse momento que entra o Code Review, garantir que as influências das pessoas em sua criança sejam as melhores possíveis.

Não pense na revisão de código como algo para apontar os erros dos outros (isso é ser babaca), pense nela como algo que vai te fazer pensar diferente sobre o seu código, além de ouvir melhorias em sua forma de desenvolver, você vai receber códigos de várias pessoas que pensam diferente de você, assim, o estilo de programar e as formas de pensar serão diferentes. Assim logo você vai começar a pensar diferente.

Usando um exemplo, pegue o SEU código de um ano atrás e procure por coisas que você melhoraria nele, prepare-se, você vai anotar muita coisa. Vou deixar a continuação dessa parte para o post de refactoring.

Além de você melhorar o seu código, você vai garantir que o projeto que você esta vai ter um futuro melhor. Quando você revisa o código de alguém, pergunta por que a pessoa tomou aquela decisão e aponta pontos que podem ser melhorados, você vai ter um código melhor em sua produção. Dessa forma você vai poder ir para a casa e saber que no dia seguinte ele vai estar bem cuidado, afinal, nós não sabemos o dia de amanhã, podemos não estar mais nesse projeto, na empresa, ou pior, um bug em produção em um código que não da para entender.

Seguem aqui dois links falando um pouco mais sobre isso e também como fazer a revisão.

https://medium.com/medium-eng/the-code-review-mindset-3280a4af0a89

https://medium.com/swlh/code-reviews-can-make-or-break-your-team-a3cfdcc15de1

E era isso. Abraço a todos

Automatizando o não automático

Aposto que você já ouviu várias pessoas falando sobre a automatização de tarefas no desenvolvimento de software e acredito que seu foco estava no Jenkins, Trevis CI e por ai vai. Depois de algum tempo trabalhando em um projeto que iniciei na empresa onde trabalho, percebi que os projetos open source tinham uma grande contribuição que ia além das ferramentas de CI.

Nos projetos que participei, notei que algumas das informações que eu precisei pedir para alguém, eu simplesmente não precisaria, essa informação poderia estar em algum lugar mais simples do que na mente de alguém, não falo em documentação em si, falo dos itens básicos para que alguém que não faz parte do seu dia a dia possa te ajudar no seu produto.

Imagine o seguinte. Você faz deploy todos os dias no ambiente de QA, ali você coloca diversas alterações de código, você garante que o código que esta ali funciona basicamente com duas coisas, testes manuais para validar aquele teste automatizado que acabou de fazer e testes automatizados, esses para garantir que não quebrou nada. Para “avançar” de ambiente, não há muita diferença, logo o maior trabalho de deploy automatizado esta em QA.

Agora, como resolver problemas de automatização com as coisas que você não precisa fazer todos os dias. Se não se faz todos os dias não precisa ser automatizado, simples, problema resolvido. Só tem um pequeno problema, sua vida não esta ficando mais fácil.

Como você resolve aquele problema de explicar para o cara novo como a banda toca? Um README.md já resolve a maior parte de seus problemas, um CONTIBUTION.md então, nem se fala. Olhe o README.md do Skeleton do ZF2, ele se explica.

Monte uma documentação pensando em alguém que chegou agora no seu time pode fazer um “hello word”, do contrário, toda a vez que uma nova pessoa chegar ela vai precisar falar com você. Ninguem chega alterando o core, simples assim, por conta disso, essa é a documentação que mais precisa ser visível.

Faça isso com um exemplo simples, formate seu computador (ou crie uma VM), você PRECISA conseguir subir seu projeto seguindo apenas a documentação do README.md e do CONTRIBUTION.md, se precisar ir no stack overflow já sabe seu próximo commit. Ou melhor ainda, use o cara novo, tudo o que ele tiver de fazer para rodar o projeto na máquina dele ele coloca na documentação.

Você não automatizou o processo da criação de uma nova máquina de desenvolvimento, mas você automatizou você, seu conhecimento agora esta em um arquivo de fácil leitura (eu acho), agora não é mais necessário chegar até você para iniciar o projeto, essa documentação já resolve o quick start.

Automatizar não é apenas para as tarefas de todo o dia e sim para tarefas repetitivas, sendo elas eventuais ou não. Toda a vez que você automatiza um processo, você reduz possíveis erros operacionais.

Apigility e Doctrine 2

Hoje vou explicar como juntar o Doctrine 2 com o Apigility. Espero que isso ajude vocês da forma como me ajudou 🙂

Baixe o Apigility por aqui.
Depois de extrair o conteúdo, inicie o servidor.

php -S 0.0.0.0:8888 -t public public/index.php

Agora vamos criar uma API
Criar o serviço REST

Depois altere as configurações do aplicativo, a Entity precisa ser alterada
Local da Entity

Agora, vamos as configurações

Primeiro vamos adicionar o Doctrine 2 como dependência, isso pode ser feito de duas formas, diretamente no arquivo.

"doctrine/doctrine-orm-module" : "0.8.*"

ou

php composer.phar require "doctrine/doctrine-orm-module" "0.8.*"

Se você fez do primeiro jeito, atualize as dependências, pela segunda forma isso não é preciso.

php composer.phar update

Agora, precisamos adicionar os módulos do Doctrine 2 no application.config.php.

'DoctrineModule',
'DoctrineORMModule',

No module.config.php, adicione a configuração para que o zend processe o doctrine

'doctrine' => array(
    'driver' => array(
        'user_entities' => array(
            'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
            'cache' => 'array',
            'paths' => array(
                0 => __DIR__ . '/../src/User/Entity',
            ),
        ),
        'orm_default' => array(
            'drivers' => array(
                'User\Entity' => 'user_entities',
            ),
        ),
    ),
),

Para finalizar as configurações, crie o arquivo que configura a conexão com o banco e depois crie na pasta data/ um arquivo database.sqlite, ele é o seu banco de dados.

A entidade User precisa ser alterada de lugar, mova ela para /src/Entity e renomeie conforme gist.

Quando as configurações e a entidade estiver criada, falta gerar as tabelas.

php public/index.php orm:schema-tool:create

Caso seja preciso atualizar o banco de dados

php public/index.php orm:schema-tool:update --force

Agora altere os arquivos que o Apigility gerou

UserResource.php

UserCollection.php

UserResourceFactory.php

Como aqui é para teste, eu inseri um registo diretamente no banco, depois disso, só usar algum programa que faz post rest, eu uso o RESTClient do Firefox.

Executando o get list

http://localhost:8888/user

Get Collection

Executando o get

http://localhost:8888/user/1

Get ID

O código pode ser baixado pelo github aqui

Qualquer dúvida só mandar e-mail ou postar aqui.

Mão na massa Restful e Zend Framework 2

Mais uma postagem da séria Mão na massa. Aqui vamos ter uma aplicação Restful usando Zend Framework 2, esse tipo de aplicação é largamente utilizada para criação de APIs e arquitetura SOA.

Particularmente eu gosto do Rest por ele ser simples, acredito que essa seja a maior vantagem dele. Muitas pessoas dizem que ele é pior do que o SOAP por questões de segurança e bla bla bla. Para você ter uma ideia, podemos usar o OAuth no Rest, acredito que isso seja o suficiente para mostrar que é seguro. Outro motivo é o fato de usar JSon, eu simplesmente acho mais legal que XML, nada mais a declarar. 🙂

Depois de falar esse monte de besteiras para você, vamos ao escopo dessa mão na massa.
Fazer um sistema que leia um CEP informado e retorne o endereço completo, o retorno deve ser em JSon e XML.
Para isso vamos fazer algo bem tranquilo, vamos apenas retornar o método get($id), com os dados fixos em um array.

Se você não tiver um ambiente pronto, eu recomendo usar o Vagrant, aqui uma postagem sobre ele e uma de como configrar um servidor LAMP.
Primeiramente vamos montar o ambiente de desenvolvimento usando o Skeleton que a Zend disponibiliza, eu tenho um fork dele na minha conta do github e é ele que vamos usar. Download Skeleton.

Depois de descompactar e deixar pronto para uso, vamos as modificações.

Sempre tenho problemas na versão do PHP, por isso vamos usar o Zend Framework 2.2, precisamos alterar o composer.

Agora vamos executar o composer

php composer.phar self-update
php composer.phar install

Assim que ele terminar de executar já podemos consultar o site, no meu caso http://cepsample.local:8080.

restfullsample

Vamos definir que a nossa URL para fazer a consulta de CEP será “/api/cep[.:format]/[:CEP]”. Como exemplos:

http://cepsample.local:8080/api.json/cep/06460000

ou

http://cepsample.local:8080/api.xml/cep/06460000

Para fazer isso, precisamos criar uma rota na nossa aplicação para ela responder por esse endereço.

cepsample/module/Application/config/module.config.php (link GitHub)

return array(
    'router' => array(
        'routes' => array(
        ...
          'cep' => array(
              'type' => 'Segment',
              'options' => array(
                  'route' => '/api/cep[.:format]/[:id]',
                  'constraints' => array(
                      'format' => '(json)',
                  ),
                  'defaults' => array(
                      'controller' => 'ApplicationControllerCep',
                      'format' => 'json',
                  ),
              ),
          ),

No mesmo arquivo, procure o indíce “controllers”, ele deve se parecer com isso

'controllers' => array(
    'invokables' => array(
        'ApplicationControllerIndex' => 'ApplicationControllerIndexController'
    ),
),

E deve ficar assim

'controllers' => array(
    'invokables' => array(
        'ApplicationControllerIndex' => 'ApplicationControllerIndexController',
        'ApplicationControllerCep' => 'ApplicationControllerCepController'
    ),
),

Com o redirect pronto, podemos iniciar a construção do método em Rest

No caminho “modules/Application/src/Application/Controller” crie um arquivo chamado “CepController.php”, ele deve ser assim:

Agora quando acessarmos a URL ele vai nos mostrar o array que foi definido no método get($id). Se não passarmos nada depois no CEP na URL, o retorno será em JSon, podemos passar XML também.

restfull_final_sample

Esse código por ser baixado pelo meu GitHub aqui.

Servidor LAMP

Hoje vou explicar como podemos criar um servidor LAMP. Essa postagem será útil se você utiliza o vagrant, sua máquina ou queria criar um servicor dentro da Amazon AWS, que é o ambiente que vamos utilizar.

Depois criarmos o servidor na AWS, precisamos acessar ele via SSH.
A primeira coisa que precisamos fazer é atualizar a lista de pacotes.

sudo apt-get update

Assim que terminar de atualizar os pocotes você pode dar início as instalações.

O primeiro passo é instalar o índio veio do Apache.

sudo apt-get install apache2

Agora, vamos a configuração de um site no apache. Com esse arquivo de exemplo, vamos montar o site.

Copie o conteúdo acima para o arquivo abaixo.

sudo nano /etc/apache2/sites-available/sample.conf

O servidor vai começar a responder para esse site apenas quando for ativado.

a2ensite sample.conf
sudo a2enmod rewrite
sudo service apache2 restart

O comando “sudo a2enmod rewrite” é para ativar o módulo de reescrita de URL do apache, ele é um adicional para o nosso caso, mas é obrigatório para o Zend, por esse motivo já coloquei ele aqui.

O segundo passo é o MySQL. Essa parte é sem segredos, vai executar o comando e ele vai pedir usuário e senha no processo.

sudo apt-get install mysql-server-5.5

Por fim, o PHP.

sudo apt-get install php5 php5-mysql

Aqui eu passei 2 pacotes para ele baixar, o “php5” é o PHP em si, o “php5-mysql” é o driver para do PHP para o MySQL.

Com tudo feito, fica assim:
Apache Sample

Postagens em inglês

Depois de algumas pesquisas para saber como eu poderia escrever um blog em dois idiomas (portugês e inglês) eu contrei o plugin para WordPress Polylang. Ele ajudou bastante na hora de fazer a organização, já montou as categorias, tags e preparou as postagens para ter mais de um idioma.

O Blog já esta com esse plugin instalado e logo eu vou começar a fazer a tradução das postagens, não encontrei ainda como colocar a bandeira do país para alterar entre os idiomas, mas isso eu arrumo logo 🙂

Assim que as postagens antigas forem traduzidas eu vou postando no Facebook e Twitter como já é de costume, aguardem.

Abraço