‫Instrutor: Então, nesta
‫aula, vamos gerenciar as senhas de nossos usuários no banco de dados.
‫E com isso, quero primeiro validar
‫se a senha inserida é igual à senha confirmada e,
‫em seguida, também criptografar a senha no banco de
‫dados para protegê-la contra ataques.
‫E então a primeira coisa
‫que faremos é validar se as duas senhas inseridas são iguais.
‫E o melhor lugar para
‫fazer isso é aqui na senha de confirmação, ok?
‫E então vamos escrever nosso validador customizado para isso, certo?
‫Então lembre-se, usamos a propriedade validate e como
‫queremos criar uma função e
‫também uma mensagem de erro, vamos abrir um novo objeto
‫aqui e ali criar um validador,
‫que será a
‫função e vamos começar com este.
‫Portanto, lembre-se, tudo o que precisamos aqui é especificar
‫uma função de retorno de chamada simples que será chamada
‫quando o novo documento for criado.
‫Portanto, função, e
‫aqui novamente, não podemos usar uma função de seta
‫porque na verdade precisamos usar a palavra-chave disk.
‫OK?
‫Então, lembre-se de que a partir da função
‫validadora retornamos verdadeiro ou falso
‫e se o valor de retorno for
‫falso, isso significa que obteremos um erro de validação, certo?
‫E, claro, se for verdade, então não.
‫E então o que queremos aqui é dizer que o elemento atual so,
‫senha de confirmação, é igual a essa senha de ponto, então, senha
‫de confirmação, é igual a essa senha de ponto,
‫e é isso mesmo!
‫Então, por exemplo, se a confirmação da senha for A-B-C
‫e a senha também for A-B-C, então,
‫é claro, isso retornará verdadeiro, certo?
‫E então a validação
‫é passada e nenhum erro ocorrerá.
‫Mas, se a senha inicial for, digamos, X-Y-Z, bem, então
‫é claro que isso retornará
‫falso e teremos um erro de validação, certo?
‫Então, muito simples, mas precisamos ter
‫em mente que isso só vai funcionar ao salvar, ok?
‫Falei sobre isso antes,
‫quando usamos o validador personalizado no modelo de tour, certo?
‫Mas estou lembrando você
‫disso aqui novamente porque isso é absolutamente crucial aqui neste ponto, certo?
‫Então, deixe-me escrever aqui para você.
‫(clique
‫do teclado)
‫Ao salvar.
‫OK?
‫E por isso, sempre que quisermos atualizar um
‫usuário, sempre teremos que usar save também
‫e não, por exemplo, encontrar um e atualizar
‫como fizemos com nossos tours, ok?
‫Portanto, vamos manter isso em mente
‫quando escrevermos o resto do código ao longo do
‫resto da seção e especialmente para atualização, ok?
‫Porque digamos que atualizamos a senha do usuário
‫simplesmente com uma atualização regular.
‫Então nesse caso, essa senha de confirmação
‫de validação que temos aqui não funcionaria mais, ok?
‫E é claro que isso não pode acontecer, ok?
‫E então, novamente, lembre-se de que isso só funcionará
‫quando criarmos um novo objeto, ou seja, criar um ponto ou salvar.
‫OK?
‫Então, ao criar e
‫salvar, Então, ao criar e salvar, tudo
‫bem?
‫Então, criamos um novo objeto usando criar, certo?
‫Então, bem aqui, usei um dot create Então,
‫bem aqui, usei um dot
‫create, mas lembre-se
‫de como também mostrei que podemos usar um ponto
‫de salvamento do usuário, assim, certo?
‫E, de fato, também podemos usar um ponto save
‫do usuário para atualizar o usuário, certo?
‫Mas, novamente, mais sobre isso um pouco mais tarde.
‫OK?
‫Então, vamos tentar essa validação aqui, certo?
‫Então, antes de mais nada, vamos tentar
‫criar um novo usuário com esses
‫dados aqui, o que não deve funcionar porque
‫já temos um usuário com esse endereço de e-mail e dissemos
‫que ele deveria ser único e, portanto,
‫não deveria funcionar.
‫Ok, então é claro nosso erro de chave duplicada, certo?
‫Ok, e então, é claro, nosso erro de chave duplicada, certo?
‫Agora, se você estivesse em
‫produção, é claro que já receberíamos nosso erro de
‫formatação agradável que criamos na última seção, certo?
‫Mas agora estamos em desenvolvimento e esse é o erro que
‫definimos que queremos ver.
‫OK?
‫Portanto, vamos simplesmente usar outro e-mail aqui e,
‫como estamos trabalhando no e-mail aqui,
‫também vamos ver como funciona a validação do endereço de e-mail.
‫Digamos que especificamos isso como nosso e-mail.
‫E assim, vemos o erro ", forneça um e-mail válido. " OK?
‫Então, vamos testar assim porque acho que também
‫não deveria ser válido.
‫Talvez seja, mas vamos ver.
‫E sim, na verdade não
‫é porque não há nomes de domínio com apenas uma letra, certo?
‫E então este validador é muito específico,
‫então é muito bom.
‫Agora, se fizermos assim, é claro que deve funcionar.
‫Mas de qualquer forma, o
‫que queríamos testar aqui são essas senhas diferentes, certo?
‫E eu me lembro agora
‫que na verdade não criamos uma mensagem de erro, eu acredito.
‫E sim, não o fizemos.
‫E então, vamos adicionar isso aqui também.
‫Portanto, mensagem,
‫não são os
‫mesmos.
‫OK.
‫Então, vamos adicionar algo aqui, não importa.
‫E agora, as senhas não são as mesmas, ok?
‫Tão perfeito.
‫E agora, é claro, nossa validação deve ser aprovada.
‫E, de fato, é e criamos nosso novo usuário.
‫Vamos ao Compass aqui, dar
‫uma olhada e, em seguida, excluí-lo para
‫que eu possa criar mais usuários com o mesmo e-mail posteriormente.
‫Tudo bem?
‫E não queremos todo esse lixo aqui
‫de qualquer maneira, então, todos esses usuários de teste, ok?
‫Mas agora, a próxima etapa é criptografar realmente essas
‫senhas simples que estamos armazenando em
‫nosso banco de dados agora.
‫Então, como mencionei no último vídeo,
‫quando estamos trabalhando com
‫autenticação, um dos princípios mais
‫fundamentais é nunca armazenar senhas simples em um banco de dados, ok?
‫Então isso é algo absolutamente inaceitável, certo?
‫Portanto, devemos sempre criptografar as senhas dos usuários, porque imagine
‫que, por algum motivo,
‫um hacker tenha acesso ao banco de dados.
‫Se as senhas estiverem armazenadas em texto simples lá, ele poderá
‫simplesmente fazer o login como qualquer usuário
‫e fazer o que realmente
‫quiser e causar muitos danos em alguns casos, certo?
‫E, portanto, precisamos evitar isso de maneira absoluta.
‫E então vamos agora implementar isso.
‫Agora, onde é o melhor lugar para realmente fazer isso?
‫Bem, eu diria que o modelo é sempre o melhor
‫lugar para fazer esse tipo de funcionalidade.
‫Então, nesse caso, a criptografia porque
‫realmente tem a ver com os dados em si
‫e então deve estar
‫no modelo e não no controlador, ok?
‫Portanto, novamente, mantenha os modelos gordos e a filosofia
‫dos controladores finos em mente aqui.
‫Tudo bem?
‫Então, como vamos implementar essa criptografia?
‫Bem, este é outro caso de uso
‫perfeito para usar o middleware Mongoose.
‫E o que
‫vamos usar é um middleware pré-salvo.
‫Então, basicamente, documente o middleware, certo?
‫Portanto, lembre-se de que definimos isso no esquema, certo?
‫E neste caso, queremos definir um
‫pré-gancho, ou seja, um pré-middleware ao salvar, certo?
‫então, um pré-middleware ao salvar, certo?
‫E a razão de estarmos fazendo
‫assim é que a
‫função de middleware que vamos especificar aqui, então a
‫criptografia, acontecerá entre o momento em que recebemos
‫os dados e o momento em que
‫eles realmente são persistidos para o banco de dados, ok?
‫Então é aí que o middleware pré-salvo é executado.
‫Entre obter os dados e salvá-los no banco de dados.
‫E esse é o momento perfeito para manipular os dados.
‫Tudo bem?
‫Então,
‫uma função, e lembre-se de que temos acesso
‫à próxima função para chamar o próximo middleware.
‫Ok, agora só queremos criptografar a senha
‫se o campo de senha tiver sido atualizado, certo?
‫Então, basicamente, apenas quando a senha é realmente alterada ou
‫também quando é criada uma nova, certo?
‫Pois imagine que o usuário está apenas atualizando o e-mail.
‫Então, nesse caso,
‫é claro, não queremos criptografar a senha de novo, certo?
‫E podemos fazer isso com o Mongoose.
‫E então vamos dizer, se e então isso, que
‫se refere ao documento atual, certo?
‫E assim, neste caso, para o usuário atual
‫e, em seguida, é modificado.
‫OK?
‫Portanto, temos um método em todos os documentos que podemos
‫usar se um determinado campo for modificado.
‫E então aqui, precisamos passar o nome do campo,
‫então "senha. " OK?
‫E então, basicamente, o que queremos
‫fazer aqui é dizer que se a senha não foi
‫modificada, então não, então, nesse caso, vamos simplesmente retornar
‫desta função e não executar nenhum outro código
‫que está aqui e então
‫chamar o próximo middleware.
‫OK?
‫Então, novamente, se a senha não foi modificada, vamos
‫apenas sair desta função
‫e chamar o próximo middleware.
‫Caso contrário, executaremos o código
‫que irei inserir aqui.
‫E agora é finalmente a hora de
‫realmente criptografar, ou como também podemos dizer, de hash a senha, certo?
‫Portanto, você verá o termo "hash" ou "hashing"
‫o tempo todo e isso basicamente significa criptografia também, certo?
‫Agora vamos fazer essa criptografia, ou hash,
‫usando um algoritmo de hash
‫muito conhecido, bem estudado e muito popular chamado bcrypt.
‫OK?
‫Portanto, este algoritmo primeiro salta e depois hash nossa senha
‫para torná-la realmente forte e protegê-la contra
‫ataques de força bruta, certo?
‫E essa é a razão
‫pela qual a criptografia precisa ser realmente forte.
‫Porque os ataques de força bruta podem
‫tentar adivinhar certas senhas se não houver uma criptografia forte.
‫E lembre-se de como eu disse que bcrypt salgará nossa
‫senha e isso significa apenas que adicionará uma
‫string aleatória à senha para que duas senhas iguais
‫não gerem o mesmo hash, ok?
‫Faz sentido?
‫Não vou entrar em todos os detalhes criptográficos de como
‫isso realmente funciona nos bastidores e
‫por que precisamos de um sistema tão complexo, certo?
‫Mas é claro que você pode ler tudo o que quiser sobre o bcrypt online.
‫Há realmente uma tonelada de coisas
‫interessantes para descobrir lá, certo?
‫De qualquer forma, vamos agora usar o pacote bcrypt
‫js para usar este algoritmo.
‫Então, npm
‫install,
‫então npm install
‫bcryptjs.
‫OK?
‫E então esta é basicamente uma implementação
‫bcrypt para Javascript.
‫OK?
‫Vamos voltar ao nosso terminal principal e,
‫em seguida, prosseguir e importá-lo aqui.
‫E este é por padrão chamado apenas bcrypt, ok?
‫E não bcryptjs.
‫(clique do teclado) Tudo
‫bem.
‫Tudo bem.
‫E agora, vamos realmente usá-lo.
‫Então, queremos dizer que esta senha de ponto, então
‫a senha atual neste documento deve
‫ser igual a bcrypt ponto hash deve
‫ser igual a bcrypt ponto hash e então
‫nossa senha atual.
‫OK?
‫E então aqui precisamos especificar um parâmetro de custo, ok?
‫E podemos realmente fazer isso de duas maneiras.
‫Então a primeira maneira será gerar manualmente o salt, de
‫forma que aquela string aleatória basicamente,
‫que será adicionada à
‫nossa senha e então usar esse salt aqui nesta função hash.
‫Tudo bem?
‫Mas, em vez disso, para facilitar
‫um pouco, também podemos simplesmente passar um parâmetro de custo
‫para essa função aqui.
‫E isso é basicamente uma
‫medida de quão intensiva será a operação da CPU, certo?
‫Acredito que o valor padrão aqui seja 10,
‫mas agora é um pouco melhor usar 12 porque
‫os computadores estão cada vez mais poderosos.
‫Então, como há 20 anos, você poderia ter usado
‫oito aqui e um pouco depois
‫de 10, mas agora, neste momento, é melhor usar 12.
‫E quanto maior for o
‫custo aqui, basicamente quanto mais intensivo de CPU
‫o processo terá e melhor será a criptografia da senha, certo?
‫E claro que poderíamos ir
‫ainda mais alto, mas então demoraria muito, certo?
‫E vou mostrar isso a você em um segundo.
‫OK?
‫Mas, por enquanto, vamos
‫realmente terminar isso porque ainda há uma coisa aqui.
‫Portanto, este hash aqui é na verdade a versão
‫assíncrona, mas também existe uma versão síncrona.
‫Mas, como você já sabe, não queremos
‫usar a versão
‫síncrona porque isso bloqueará o loop de eventos e evitará
‫que outros usuários usem o aplicativo.
‫Assim como aprendemos no início.
‫E é claro que
‫queremos usar a versão assíncrona que é esta.
‫E isso então retornará
‫uma promessa e essa promessa, é claro, precisamos aguardar.
‫E então, precisamos usar await e dizer que essa função
‫é uma função assíncrona, exatamente como esta.
‫Então, vamos recapitular isso aqui.
‫Então, queremos definir nossa senha atual basicamente
‫para criptografar esta versão da senha original com um custo de 12,
‫não para tornar muito fácil
‫quebrar a senha, mas também para não fazer o aplicativo
‫demorar muito para criptografar a senha, tudo bem?
‫Com isso, criptografamos nossa senha e
‫agora no final, o que
‫precisamos fazer é basicamente deletar a senha de confirmação, certo?
‫Porque, neste momento,
‫só temos a senha real hash, certo?
‫Então, essa senha de ponto
‫confirma, Então,
‫essa senha de ponto confirma, e como
‫basicamente excluímos o campo, para não ser persistido
‫no banco de dados é defini-lo como indefinido.
‫Tudo bem?
‫Então, nós realmente só precisamos confirmar essa senha aqui
‫para a validação que implementamos antes.
‫Então, apenas para ter certeza
‫de que o usuário realmente inseriu duas senhas
‫iguais para que ele não cometa nenhum erro com sua senha.
‫Direito?
‫E assim, depois que essa validação
‫foi bem-sucedida, não precisamos mais desse campo,
‫então realmente não queremos persisti-lo no banco de dados.
‫E é por isso que simplesmente definimos aqui como indefinido.
‫Tudo bem?
‫Agora você deve estar se perguntando por
‫que isso funciona, porque na verdade definimos a confirmação
‫da senha como obrigatória, certo?
‫Mas isso significa simplesmente que é uma entrada
‫obrigatória, não que seja realmente persistido no banco
‫de dados, certo?
‫para o banco de dados, ok?
‫Agora, só para terminar, é claro que também precisamos ligar em seguida.
‫OK?
‫Vamos dar uma chance.
‫E, na verdade, vou adicionar alguns
‫comentários aqui para deixar bem claro para você.
‫Basicamente, o que isso faz é executar essa
‫função
‫apenas se a
‫senha tiver sido realmente modificada.
‫Então
‫aqui, hash a senha com custo de 12.
‫Em seguida,
‫exclua o campo de confirmação de senha.
‫OK.
‫E agora, vamos testar isso.
‫E agora vou criar um novo usuário exatamente com esses dados
‫e vamos agora dar uma olhada no resultado.
‫E, de fato, agora temos essa senha de aparência muito estranha
‫que, de fato, é a versão criptografada de pass1234.
‫E também, como você pode ver, a confirmação da senha não está mais aqui.
‫OK?
‫E assim, agora armazenamos os usuários de forma
‫segura em nosso banco de dados.
‫Deixe-me mostrar como funcionará se, por
‫exemplo, definirmos como 16 aqui.
‫E preciso mudar o e-mail aqui.
‫E isso agora deve levar muito tempo e não
‫tenho certeza se posso esperar.
‫Oh, na verdade, demorou cerca de quatro segundos e meio.
‫Mas isso ainda é um pouco demais, eu acredito, ok?
‫Então, vamos definir de
‫volta para
‫12 e assim deve ser melhor, ok?
‫E agora vamos, novamente, excluir
‫esses usuários aqui que acabamos de criar.
‫E na verdade eu preciso me livrar
‫deste primeiro porque este ainda tem a senha em texto simples.
‫E, portanto, esse usuário não funcionará
‫quando começarmos a realmente fazer o login
‫de usuários com base em suas senhas.
‫OK?
‫Então, vamos nos livrar disso.
‫OK?
‫E também o que eu queria
‫mostrar aqui é que colocamos exatamente a mesma
‫senha para esses dois usuários que criamos, certo?
‫Mas você vê que a
‫senha criptografada é na verdade muito diferente, certo?
‫E esse é o poder de criar sal na senha
‫antes de fazer o hash.
‫Tudo bem?
‫Assim, de novo, implementamos um gerenciamento de senha muito
‫seguro e bom.