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.

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.