Transcrições
1. Introdução do curso: Bem-vindo de volta ao curso
Express Jazz, Modelo nove, autenticação
e autorização. Meu nome é ShenRagunhi e serei seu instrutor Ao longo dos anos, tive o privilégio de
criar sistemas de back-end seguros e
escaláveis para
uma variedade de aplicativos e estou aqui para compartilhar
minha experiência Um dos meus melhores projetos
envolveu a criação um sistema de autenticação de usuário
para uma plataforma de comércio eletrônico, o que melhorou significativamente
sua segurança e usabilidade Hoje, você aprenderá a construir algo
igualmente impactante Neste módulo, vamos nos
aprofundar na autenticação
e autorização, dois aspectos críticos do desenvolvimento web
moderno. Assim, você aprenderá como registrar usuários com segurança usando senhas com
hash,
autenticar usuários
com os webtkens da JCN, proteger
rotas confidenciais com middleware
e, finalmente, implementar a autorização baseada em funções para gerenciar as permissões finalmente usuários com segurança usando senhas com
hash,
autenticar usuários
com os webtkens da JCN,
proteger
rotas confidenciais com middleware
e, finalmente, implementar a autorização baseada em funções para gerenciar as permissões do usuário. Esse conhecimento é crucial para proteger qualquer aplicativo de
back-end
e, ao final deste módulo, você estará confiante na
implementação desses
recursos em seus projetos Portanto, este módulo foi projetado
para Bg em desenvolvedores que desejam levar seus
aplicativos Express JS para o próximo nível. Se você concluiu
os módulos anteriores, está tudo pronto para começar. conhecimento básico de JavaScript, recomendado o conhecimento básico de JavaScript,
sem JS e Monger
DB Autenticação e
autorização são os pilares de qualquer aplicativo web
seguro Ao dominar esses conceitos, você não apenas criará aplicativos
mais seguros, mas também aumentará seu
valor como desenvolvedor Essas são
habilidades essenciais para criar plataformas centradas no
usuário
no mundo tecnológico atual E, finalmente, para o projeto, você integrará
tudo o que aprendeu no aplicativo
Fair Wheels. Então, mais especificamente,
você implementará funcionalidade de registro e
login de
usuários, autenticando usuários
com segurança
usando tokens da web JCN Aplique autorização baseada em funções para proteger rotas e recursos. Ao final, você terá um sistema de gerenciamento de
usuários seguro e escalável para o aplicativo Fair Wheels Este módulo é um divisor de águas para sua jornada de
desenvolvimento do Bend Então, vamos criar
aplicativos seguros juntos. vejo na primeira
palestra. Vamos começar.
2. Autenticação e autorização - Uma introdução: Tudo bem, então, de volta ao nosso aplicativo
Fair Wheels. Até agora, criamos
esses endpoints de API. Assim, podemos gerenciar empresas, carros, clientes e aluguéis. Agora, quase todos os
aplicativos existentes exigem algum tipo de
autenticação e autorização. Então, nesta seção,
vamos levar esse
aplicativo para o próximo nível e implementar autenticação
e autorização. Portanto, antes de prosseguirmos, quero ter certeza de que
estamos na mesma página. Portanto, a autenticação
é o processo de identificar se o usuário é
quem afirma ser. É quando fazemos o login. Então, enviamos nosso usuário e
senha para o servidor, e o servidor nos autentica A autorização é determinar se o usuário tem a permissão
correta para realizar a operação em questão. Portanto, em nosso aplicativo Fair
Wheels, queremos garantir que
somente usuários autenticados
ou somente usuários logados possam realizar operações
que modifiquem dados Portanto, se o usuário for anônimo, se não estiver conectado, ele só poderá ler os dados
desses endpoints Se eles quiserem criar uma nova
empresa ou atualizar um carro, eles precisam ser
autenticados primeiro Agora, como segurança adicional, queremos garantir que somente usuários administradores
possam excluir dados. Então, esse é um segundo
nível de autorização. Estamos falando sobre
permissões aqui. Então, esses são os requisitos que vamos implementar
nesta seção. Então, para fazer isso, precisamos
adicionar dois novos endpoints
ao nosso aplicativo Primeiro, devemos ser
capazes de registrar usuários. Para isso,
enviaremos uma solicitação de postagem para slash
API slash USERS porque publicamos, criamos novos recursos Nesse caso, um novo usuário. Também devemos ser capazes de
fazer login com um usuário, e isso é usado para
autenticação. Agora, aqui está uma pergunta para você. Qual método SDDP devemos
usar para implementar o login? Porque com o login,
não estamos criando um novo recurso. Não estamos atualizando ou
removendo um existente. Então, como podemos implementar
isso em termos tranquilos? Esse é um daqueles
cenários que você pode encontrar com frequência em aplicativos do mundo
real. Às vezes, a operação com a qual você está lidando não
tem essa semântica de criação, leitura, atualização e exclusão A forma como modelamos isso
em termos repousantes é referindo a isso
como solicitação ou comando Então você está criando uma nova solicitação de
login ou
um comando de login. Nesse caso, usaremos post porque estamos
criando um novo recurso, então slash API slash Logins Agora, em seu aplicativo, talvez você queira armazenar
todos os logins
no aplicativo em uma
coleção separada no Mongo Então, você pode ver que usar a postagem
faz todo o sentido aqui. Mas mesmo que você não armazene logins
individuais e queira
apenas validar
o usuário e a senha, você ainda pode tratar
esse recurso como recurso login e usar
post para criá-lo Agora, aqui está um exercício para você. Quero que você implemente essa
API para registrar novos usuários. Então, para cada usuário, queremos ter
essas propriedades, nome, e-mail e senha. Além disso, ao definir
seu esquema para a propriedade de e-mail no objeto
do tipo de esquema, defina a propriedade exclusiva Então, quando definimos o esquema, definimos o tipo de e-mail para um objeto que é nosso objeto de tipo de
esquema Definimos o tipo aqui como string e também definimos exclusivo como verdadeiro. Então, com isso, garantimos
que não armazenaremos dois documentos com o
mesmo e-mail no Mongo Di B.
Ok. Então, vá em frente e implemente somente essa API
para registrar novos usuários. Eu vou fazer o mesmo
na próxima palestra.
3. Criando o modelo do usuário: Tudo bem. Então, primeiro, vou definir
um novo modelo de usuário. Então, aqui na pasta de modelos
em um novo arquivo user dot js. Agora, para economizar tempo,
vou até a
empresa dot js e pego emprestado
um código daqui Então copie de volta para userdtjs,
cole aqui. Agora, no topo,
temos esse esquema. Vou definir isso ao
chamar o método do modelo. Realmente não há necessidade,
neste caso, de definir isso
como uma constante separada. Então, vamos pegar esse
objeto de esquema e adicioná-lo aqui. E agora podemos nos
livrar desse esquema. Ok, isso é melhor. Então esse é o nosso modelo. Devemos chamar esse usuário
constante. E a coleção correspondente também
deve ser de usuários. Agora, aqui, temos a
propriedade name, que é uma string. É obrigatório e tem de
5 a 50 caracteres. Isso
soa bem para mim. Em seguida, vamos adicionar e-mail. Então, vou pegar tudo
isso de bom e duplicá-lo. E a segunda
propriedade é o e-mail. Então, novamente, temos
essas propriedades. Eu gostaria de aumentar
o tamanho máximo para 255 caracteres Além disso, como eu disse
na última palestra, devemos adicionar a
propriedade exclusiva para garantir que
não armazenemos dois usuários com
o mesmo e-mail no Manga Divi E a última propriedade é Passwb. Então, vou copiar tudo isso, duplicar e adicionar essa propriedade de
senha Agora vou definir o tamanho
máximo das senhas para um valor maior porque
vamos fazer o hash
dessas senhas E aqui não precisamos
da propriedade exclusiva. A seguir, nossa função de validação. Portanto, precisamos renomear
isso para validar o usuário. Valide o usuário que
usa um parâmetro do usuário. Aqui temos um nome de 5 a 50 caracteres
e é obrigatório Temos um e-mail, que deve
ter de 5 a 255 caracteres. Deveria ser obrigatório.
E aqui também chamamos o método de e-mail para
garantir que seja um e-mail válido. E, finalmente, temos a senha, que também é uma string com mínimo cinco caracteres
e no máximo, digamos, 255, conforme necessário Então essa é a senha que o usuário envia em texto simples. Vamos fazer um hash disso, que
será uma sequência mais longa,
e essa é a sequência que
armazenaremos na Mongo TV Então, terminamos com nossa função de usuário
válida. Agora precisamos exportar
nosso modelo de usuário, então não precisamos da
primeira instrução de exportação que é para nossa exclusão de esquema Aqui vamos
exportar isso como usuário, e nossa
função de validação também é boa Linda. Então, terminamos
com nosso modelo de usuário. Na próxima palestra,
adicionarei uma rota para registrar novos usuários
4. Registrando usuários: Tudo bem Agora vamos criar uma nova rota para
registrar novos usuários. Então, aqui na pasta routes, vou adicionar um novo
arquivo users dot js. Agora, mais uma vez, para economizar tempo, vou até
as empresas dot js e copiarei essas
declarações obrigatórias, bem
como a segunda rota,
em nosso novo módulo. Então copie, cole aqui. Novamente, copie a rota da postagem. E cole aqui. E, a propósito, só
estou fazendo isso porque não
quero perder seu tempo me vendo
digitar tudo isso à mão. No mundo real,
você deve evitar abordagem de
copiar e colar, a menos que seja
muito cuidadoso e leia
cada linha
do código copiado para ter
certeza de que não cometeu um erro É sempre melhor
digitar o código manualmente. Agora, vamos fazer mudanças. Então, no topo, precisamos importar o
modelo do usuário em vez da empresa. Então, do usuário de modelos, importamos a classe de usuário, bem
como a função de
validação Também precisamos do Express e do Router. Então, aqui está nossa nova rota que é proposta para criar novos usuários. E, finalmente, precisamos
exportar esse roteador. Então, module dot Exports. Nós configuramos isso para este roteador. Agora, precisamos voltar ao nosso ponto de índice JS
e dizer ao Express que, para qualquer rota que
comece com a barra ABS SRS, devemos usar esse roteador
que estamos exportando aqui Então, vamos para Index ou Js. Na parte superior, vamos
importar esse novo módulo. Então, usuários constantes. Definimos isso para exigir dos usuários
da pasta de rotas. E então aqui chamamos o
aplicativo que dá ao nosso caminho barra de usuários de APAs e nosso
roteador, ou seja, usuários Ok, então nós construímos
o quadro geral. Agora, vamos voltar ao nosso
módulo de usuários e implementar
essa nova rota. Então, aqui vamos
validar a solicitação. Se não for válido, retornaremos um erro 400, que
é uma solicitação incorreta. Caso contrário, criaremos um novo objeto de usuário e o
salvaremos no banco de dados. Então, vamos manter as duas primeiras linhas
exatamente como estão. Queremos validar a solicitação. Estamos usando nossa função de
validação Joy. Portanto, se as propriedades de nome, e-mail ou senha não
forem válidas, retornaremos um erro
400 ao cliente. Agora, em seguida, precisamos fazer
outro tipo de validação. Você quer ter certeza de que esse usuário
ainda não está registrado. Então, chamamos o usuário dot Fine one, passamos um objeto de consulta aqui. Estamos procurando um usuário com um determinado e-mail que é
request dot body dot email. Então, observe que aqui, eu não usei fine by
ID porque
não estamos procurando o
usuário pelo ID. Estamos procurando por
uma de suas propriedades. Tão bom. Agora, isso
retorna uma promessa. Então, aguardamos e
obtemos um objeto de usuário. Agora, nesse caso, estou
definindo uma variável em vez de uma constante porque
vamos
redefinir isso, como você
verá em um segundo. Portanto, nesse caso, se
tivermos esse
objeto de usuário no banco de dados, devemos retornar um erro de
solicitação incorreta ao cliente. Então, retorne a resposta
dot status 400, que é uma solicitação inválida dot SEND e aqui está a mensagem que o
usuário já registrou. Então, neste momento, temos
um objeto de usuário válido. Esse usuário não está registrado
no banco de dados, então precisamos salvá-lo no banco de dados. Então, aqui, vou redefinir esse objeto de usuário porque,
neste momento, ele deveria ser não. Definimos isso para um novo usuário e aqui definimos as propriedades. Então, nome, definimos isso para
solicitar corpo do ponto, nome do ponto. E-mail para solicitar e-mail
dot body dot. E senha para solicitar a senha do corpo do
ponto. Então esse é o nosso objeto de usuário. Agora vamos salvá-lo. Então aguarde, o usuário salve
e, finalmente, devolva
isso ao cliente Portanto, não precisamos dessas duas linhas para trabalhar com a empresa. Excluir. E, finalmente, devolva esse novo usuário ao cliente.
Agora, vamos testar isso. Então, de volta ao Postman, vou enviar
uma solicitação de postagem para 3.000 usuários slash APAS da porta
Local Host E então, no corpo
da solicitação, vou definir isso como Raw
e definir o tipo como JSON Aqui passamos como objeto JSON
com três propriedades,
nome, Shiv, depois configuramos e-mail Vou definir
um e-mail inválido e também não vou definir
a senha Quero ter certeza de que nossa função de
validação
está funcionando corretamente. Então mande. Ok,
recebemos um pedido ruim. Isso é bom. O tamanho do nome deve ter pelo menos cinco
caracteres. Então, deixe-me mudar isso
para Hewnder Alright. Agora vamos enviar outra solicitação. Recebemos outro pedido incorreto. O tamanho do e-mail deve ter pelo
menos cinco caracteres. Então, vamos mudar
isso para 12, três, quatro, cinco, seis, mas esse não
é um e-mail válido. Então, agora devemos receber
um erro diferente. O e-mail deve ser válido. Linda. Então, vamos mudar isso para testar 123 em regmil.com Vamos enviar outra solicitação. Ok, agora temos
a senha necessária. Linda. Por fim, vamos adicionar uma senha com pelo menos
cinco caracteres. Então, um, dois, três,
quatro, cinco, envie. Desta vez, obtivemos uma resposta de 200. Linda. E esse é o objeto do usuário que você
armazenou no banco de dados. Então você tem a propriedade ID,
bem como nome, e-mail
e senha. Agora, ao registrar
um novo usuário, não
queremos devolver sua
senha ao cliente Então, isso é algo que
vamos
corrigir na próxima palestra. Mas vamos enviar outra solicitação com exatamente os mesmos valores. Desta vez, devemos
receber um erro diferente, informando que o usuário já
está registrado. Então mande. Ok, recebemos
outro pedido incorreto, e aqui está a mensagem. Usuário já
cadastrado. Linda. Então, na próxima aula, vamos modificar a
resposta dessa API e do ponto
5. Usando o Lodash: Então, de volta ao nosso método post, queremos modificar a
resposta para o cliente. Portanto, há duas opções aqui. Uma abordagem é retornar
um objeto personalizado como esse, definindo o nome como nome
do ponto do usuário
e o e-mail como e-mail ponto do usuário. Dessa forma, podemos excluir a senha e as propriedades da
versão. Essa abordagem é
perfeita, mas nesta palestra, apresentarei
uma biblioteca útil que oferece muitas funções
utilitárias para trabalhar com objetos Se você é um desenvolvedor experiente em
JavaScript, provavelmente sabe do que estou falando. Isso é Lourdes Então acesse lodash.com. Isso é lodash, que é basicamente a
versão otimizada do sublinhado O underscore já
existe há muito tempo. Ele tem muitos mecanismos utilitários
para trabalhar com objetos, sequências de caracteres, matrizes e assim por diante Portanto, se você consultar
a documentação, aqui podemos ver todas
as funções utilitárias que temos para trabalhar
com vários tipos. Temos muitas funções
utilitárias para trabalhar com matrizes,
números, cadeias de caracteres,
objetos e assim por diante Portanto, o lodash é extremamente poderoso. E nesta palestra,
mostrarei como usá-lo em
seu aplicativo node Então, de volta ao terminal, o
NPM instala o lodash. Portanto, observe que na
versão atual estou usando 4.17 0.21. Tudo bem, agora, de volta ao código. Então, aqui no
modelo do nosso usuário na parte superior, vou importar o Lodash Então, exija o Lodash. Agora, por convenção, armazenamos o resultado em uma constante
chamada sublinhado Você pode chamar isso de qualquer coisa, você pode chamar isso de Lodash, mas por convenção, usamos sublinhado porque
é curto Agora, esse
objeto de sublinhado que
temos aqui tem um método
utilitário chamado pick so underscore dot Nós damos a isso um objeto. Nesse caso, nosso objeto de usuário
e, em seguida, passe uma matriz
de propriedades
nesse objeto de usuário que
queremos escolher. E isso
retornará um novo objeto com apenas essas propriedades. Então, aqui nesta matriz, vou passar
nome e e-mail. Então, quando chamarmos
esse método de seleção, obteremos um novo objeto com essas duas propriedades,
nome e e-mail. Agora, em vez de
repetir manualmente o ponto do usuário, podemos usar esse método Pi Isso é mais elegante. Então, podemos substituir esse objeto aqui pelo que obtemos
do método PI. simples quanto isso.
Agora, talvez aqui, você também queira incluir
a propriedade IR. Então é assim que
usamos o método PIC. Da mesma forma, podemos
modificar esse código
e, em vez de repetir a
solicitação ponto no corpo do ponto, solicitar ponto no corpo do ponto, solicitar ponto no corpo do ponto
com sublinhado no ponto Então, vou
substituir esse objeto underscore dot pig Pedimos que pague. Agora, aqui, podemos
ter 50 propriedades. Um usuário mal-intencionado pode
nos enviar propriedades para serem
armazenadas no banco de dados. Só queremos
escolher alguns deles a dedo. Então, passamos uma matriz. Estamos interessados apenas em
nome, e-mail e senha. Ok, então criamos
o usuário e o
salvamos e, em seguida, retornamos esse objeto
personalizado ao cliente. Vamos testar isso mais uma vez para garantir que
tudo esteja funcionando. Então, terminal de back-end. Vamos executar o aplicativo. Linda. Agora, de volta
ao Postman Vou enviar uma nova solicitação
pelo servidor. Enviar. Ok, aqui está nosso
novo objeto de usuário. Só temos ID,
nome e e-mail. Agora, em todas essas
solicitações até agora, enviei senhas muito
simples. Se você quiser impor a complexidade da
senha, existe um pacote NPM
baseado no
Joy chamado Joi
password Complexity Joy chamado Joi Então, de volta ao Google, pesquise
Joy password Complexity. Esse é o pacote NPM. Então, com isso, você pode
configurar um objeto que determina a
complexidade da senha em seu aplicativo. Número mínimo de
caracteres, máximo, quantas letras
minúsculas ou maiúsculas você deseja ter, quantos números e assim por diante. Portanto, o nome do pacote
é Joy password complexity. Neste curso, não vamos usar isso porque é
algo que você pode
fazer sozinho. Tudo bem, nosso novo
endpoint de API está em boas condições, mas estamos armazenando nossas
senhas como texto simples, e isso é muito, muito ruim Então, na próxima palestra, mostrarei como
fazer o hash dessas senhas
6. Hashing de senhas: Nesta palestra,
mostrarei como
fazer hash de senhas Para isso, vamos usar uma biblioteca muito popular
chamada B crypt. Então, aqui no terminal, vamos instalar o B crypt. Instalar. Observe a
versão que estou usando. Essa é a versão 5.1 0.1. Agora, aqui, vou
criar um arquivo de playground, para que você aprenda a trabalhar
com essa biblioteca BCRP
e, em seguida, vamos
pegar esse código e colocá-lo em uma rota para codificar a
senha de Então, vamos criar um novo
arquivo, hash dot js. Neste arquivo, primeiro, precisamos carregar o BCRP Isso retém um objeto. Nós o armazenamos aqui. Cripta B. Agora, para ter uma senha, precisamos de um sal. O que é sal? Bem, imagine que nossa senha
seja um, dois, três, quatro. Quando fizermos o hash, vamos imaginar que obteremos
uma string como essa Agora, esse
algoritmo de hashing é uma maneira. Então, se temos A, B, CD, não
podemos decifrar isso e
obter um, dois, três, quatro Então, do ponto
de vista da segurança, isso é ótimo. Se um hacker
examinar nosso banco de dados, ele ou ela não conseguirá decifrar essas senhas
criptografadas No entanto, eles podem
compilar uma lista de senhas
populares e criptografá-las. E então eles podem consultar o banco de dados do nosso aplicativo. Eles encontram essa senha hash e sabem que ABCD
representa um, dois, três, quatro É por isso que precisamos de um SALT. Pois SALT é basicamente uma string aleatória que é adicionada antes ou
depois dessa senha. Portanto, a
senha com hash resultante será diferente. Cada vez com base na
agressão usada. Ok, deixe-me
mostrar isso em ação. Então, aqui chamamos B
crypt dot Gen SLT. Observe que esse método
tem duas versões. O primeiro é assíncrono. O segundo é síncrono. Como prática recomendada, você deve sempre usar métodos
assíncronos porque, como eu disse no
início do curso, em aplicativos de nós,
temos um Não queremos manter
esse tópico ocupado porque não podemos
atender outros clientes. Então, chamamos GenSLT
como argumento. Nós passamos o número de franzidas. Queremos executar esse algoritmo
para gerar o SLT. Quanto maior o número,
mais tempo será necessário para
gerar o sal. Além disso, o SOT
será mais complexo e
difícil de quebrar Portanto, o valor padrão é dez. Vamos usar isso agora
porque esse é um método
assíncrono Podemos repassar o
retorno de chamada aqui, e é isso que você vê na documentação oficial
deles, bem
como em muitos
tutoriais na web. Mas esse método também tem uma sobrecarga que
retorna uma promessa Então, em vez
de enviar um retorno de chamada, recebemos uma promessa, aguardamos e depois recebemos o sal Então, agora precisamos envolver isso em uma função de atuação como run Ok, então vamos colocar esse
sal no console. E, finalmente, vamos chamar
essa função de execução. Agora, de volta ao nó
terminal tem dois Js. Então esse é um exemplo de sal. Você pode ver o número de rodadas que usamos incluídas no sal Então, se usarmos 20 aqui em vez
de dez, teríamos 20. Então, aqui temos uma
longa sequência aleatória que é incluída como parte
do hash de nossas senhas E com isso, toda vez que criptografamos nossa senha
com um novo Salt, obtemos resultados diferentes Então, agora que temos um Salt, podemos usá-lo para codificar
nossa senha Temos outro método aqui
neste objeto da cripta B
que é o hash Então, fornecemos nossos dados. Vamos imaginar que nossa
senha seja um, dois, três, quatro, e
dê o sal a ela. E, novamente, veja, o terceiro
argumento pode ser um retorno de chamada. Não vamos usar isso. Em vez disso, receberemos
a promessa que é
retornada desse método. Então, aguardamos essa promessa e
recebemos a senha criptografada. Então, agora vamos registrar isso
no console também. Hashado. Ok, de volta ao nó
terminal, hashed ou chase Ok, olha, na primeira
linha, temos nosso sal. Na segunda linha, você também pode
ver o sal aqui. Portanto, o SALT é incluído
na senha com hash. A razão pela qual isso está incluído é porque, posteriormente, quando quisermos
autenticar o usuário, queremos validar seu
nome de usuário e senha Então, o usuário envia uma
senha em texto simples. Precisamos fazer o hash novamente, mas precisamos ter
o sal
original usado para
gerar esse hash Portanto, ao comparar a senha de texto
simples com a senha com hash, B crypt precisa saber o sal original
usado para fazer o hash Agora que você sabe
como o B Crypt funciona, vamos pegar essas duas linhas e colocá-las em
nosso manipulador de rotas Então corte-os daqui. Vamos até os usuários dot js. Ok, aqui está nosso objeto de usuário. Vamos colar essas linhas aqui. Então, geramos um sal
e, em seguida, precisamos
ter a senha. Em vez de um,
dois, três, quatro, vamos usar a senha de ponto
do usuário. Essa é uma senha em texto simples. Então, misturamos com
sal e depois reiniciamos. Então, senha do ponto do usuário. Agora, no topo, também
precisamos importar a cripta B,
portanto, a cripta B constante Definimos isso para exigir o Bcrypt. Agora, aqui no Compass, quero excluir a coleção do
usuário porque todos os usuários que
temos até agora têm senha em texto simples Então exclua. Tudo bem. Agora, de volta ao terminal, vamos executar o mod Node. E então aqui no Postman, vamos
enviar uma nova solicitação S. Linda. Então, aqui temos um novo usuário. Agora, de volta ao Compass, vamos atualizar a lista Temos a coleção do usuário, e aqui está nosso novo usuário
com uma senha criptografada Linda. Então, implementamos esse endpoint
para registrar novos usuários Nós terminamos aqui. A seguir, analisaremos a
autenticação de usuários
7. Autenticando usuários: Tudo bem, então aqui
na pasta de rotas, vamos adicionar um novo arquivo. Chamamos isso de logins
dojs ou auth dot js. Qualquer um deles funciona, mas a
autenticação é mais comum. Então, autentique-nos. Novamente, você economiza tempo, vou pegar um código emprestado Então, vamos até os usuários dot js. Vou copiar todo o código que escrevemos nesta seção e depois colar em auth dot js Agora, antes de
entrarmos nos detalhes, vamos ao index dot JS. Na torneira, importe
esse novo módulo. Então, Cs OT, configuramos isso
para exigir rotas OT. Portanto, se tivermos alguma solicitação
para esse endpoint, cortar a API OT ou um de
seus endpoints secundários, delegaremos
isso ao roteador Então, o panorama geral está pronto. Agora vamos dar uma olhada nos detalhes. Então, de volta ao módulo Auth, na parte superior, primeiro, precisamos validar o
corpo da solicitação Mas essa
função de validação que temos aqui é a que
importamos do nosso módulo de usuário Então, isso está validando isso. No corpo da solicitação, temos três propriedades, nome, e-mail e senha. E no aplicativo do
mundo real, você pode ter outras propriedades como parte do registro de um usuário Portanto, essa função de validação serve
para validar um novo usuário. Não é para validar
o e-mail e senha que esperamos
neste endpoint Então, aqui precisamos de uma função de
validação diferente. Então, vou remover essa função de
validação
daqui e definir uma
função de validação separada neste módulo Agora, para economizar tempo,
vou para o módulo
do usuário e copiarei
essa função de validação Portanto, validamos o usuário. Vamos copiar isso de volta
para o módulo Auth, colá-lo aqui e, em seguida,
alterá-lo para validar Agora podemos alterar o
parâmetro a ser solicitado. Agora, para esse objeto de esquema, precisamos apenas de duas propriedades,
e-mail e senha Então, vamos excluir o
nome e pronto. Então, voltando ao nosso manipulador de rotas, esta é nossa primeira validação Em seguida, precisamos ter certeza que temos um usuário
com um determinado e-mail. Então, carregamos o usuário. Se não tivermos o usuário
, aqui aplicamos
o operador not. Se não tivermos o usuário, devemos enviar um
erro 400 ao cliente, o que significa que a solicitação
e a mensagem devem ser um e-mail ou senha inválidos Observe que aqui, não estou
enviando um quatro ou quatro, o que significa não encontrado
porque não queremos
dizer ao cliente por que a
autenticação falhou. Não queremos
saber se esse e-mail ou
a senha estão corretos. Portanto, não queremos dizer que
não temos um usuário
com um determinado e-mail. Nós apenas dizemos ao cliente
que essa é uma solicitação incorreta. Ele não tem os
dados corretos para serem processados. Portanto, isso é para validar o nome de usuário e o
e-mail neste caso Em seguida, precisamos
validar a senha. Para isso, precisamos usar o BCRP. Então, vamos deletar todo esse código. Esse objeto da cripta B que temos
tem um método de comparação. Usamos isso para comparar uma senha de texto simples
com uma senha com hash Portanto, nossa senha de texto simples está na senha de ponto
do corpo do ponto da solicitação, e nossa senha hash está
no usuário dessa senha Então, como você viu anteriormente, essa senha hash
inclui o SLT Então, quando chamamos o método de
comparação, B crypt
pega esse sal e o usa para restaurar essa senha de texto
simples Se forem iguais,
isso retornará verdadeiro. Então, aqui precisamos aguardar essa promessa e armazenar o
resultado aqui em uma senha válida Agora, se a senha não
for válida, novamente, retornaremos um erro 400 com essa mensagem vaga, e-mail ou senha
inválidos Então, vou copiar
isso e colar aqui. E, finalmente, se
chegarmos até aqui, isso significa
que esse
é um login válido. Então, por enquanto, eu só
quero enviar um valor simples e verdadeiro para o lint.
8. Testando a autenticação: Então, por enquanto, vamos testar
essa rota de autenticação. Antes disso, então um ponto é. Aqui, esqueci de
mencionar load joy. Então, deixe-me fazer isso rapidamente. Last Joy,
defina isso para exigir Joy. Ok. E na parte inferior da função
de validação, aqui precisamos retornar a solicitação de validação de pontos do
esquema Ok, então estamos prontos. Vamos abrir o postmin. Então, aqui vou
abrir uma nova guia. Vamos selecionar a postagem aqui. Deixe-me digitar o endpoint. É TP, host local OT, API OT. E no corpo da solicitação, vou enviar o GSN. Então, deixe-me selecionar Json aqui. E agora temos dois parâmetros. Então, o primeiro é o e-mail. O e-mail
que usamos é 23,
quatro, cinco, seis, sete, na taxa gmail.com E nossa senha é um, dois, três, quatro, cinco. Então, deixe-me enviar esse pedido, SN. Linda. Temos
um status 200. Ok. E aqui está nossa resposta. Agora, deixe-me alterar
a senha aqui para algo como 67 e
depois enviar a solicitação novamente. Veja, temos uma solicitação inválida de 400
e o comando genérico, que é
e-mail ou senha inválidos Agora, vamos alterar o e-mail para outra
coisa com
a senha correta. Então, algo assim. E deixe-me enviar o
pedido novamente. Então mande. Veja, novamente, temos
uma solicitação inválida de 400 e a mensagem genérica que é
e-mail ou senha inválidos Portanto, nosso
endpoint de autenticação está funcionando bem. Na próxima palestra, veremos
a resposta
que estamos enviando
aqui e a alteraremos para algo que chamamos de token da web
adjacente
9. Tokens da Web JSON: Portanto, temos um endpoint
para autenticar usuários. Agora, precisamos modificar
a resposta aqui
e, em vez de
retornar um valor verdadeiro, precisamos retornar
um token web JCN webtoken AJCN é basicamente uma longa string que
identifica Como metáfora, você
pode pensar nisso
como sua carteira de motorista
ou seu passaporte É muito parecido com isso. Então, quando o usuário faz login
no servidor, usamos esse token web JCN, que é como uma
carteira de motorista ou passaporte, nós o entregamos ao cliente
e dizemos a ele: Ei, próxima vez que você quiser voltar aqui
e ligar
para um de
nossos endpoints de API, você precisará mostrar Você precisa mostrar sua carteira de
motorista. Esta é a sua identidade. Então, no cliente, precisamos
armazenar esse token web JCN, que é uma sequência longa, para que possamos enviá-lo de volta
ao servidor para futuras chamadas de API Agora, o cliente pode ser um aplicativo web ou
um aplicativo móvel. Se for um aplicativo web, se você estiver criando um aplicativo
com angular ou react, poderá usar o armazenamento local. Esse é um local
de armazenamento especial que está disponível em todos os
navegadores existentes. Se você estiver criando um aplicativo móvel, você tem uma opção semelhante dependendo da
plataforma que você usa. Então, agora deixe-me mostrar um
exemplo de AJCnwbtken. Vá até o ponto II. Neste site, temos aqui um depurador para trabalhar
com JS Então, aqui na seção codificada, você pode ver um exemplo real
do token Web AJCN Essa longa string que você vê na
seção codificada representa um JCNobr, então, quando decodificarmos isso, obteremos Está bem? Agora podemos ver que
essa string tem três partes, e cada parte é um código de cores. Então, a primeira parte é vermelha, a segunda parte é roxa e a terceira parte é azul. No lado direito, você pode
ver essa string decodificada. Portanto, a parte vermelha é o que
chamamos de cabeçalho de
um token web JCN Neste cabeçalho,
temos duas propriedades. Um é L, que é a
abreviação de algoritmo que determina o algoritmo usado para codificar esse token O tipo é GWT, que é o token da web JCN Agora, nunca mais precisamos nos
preocupar com esse cabeçalho. É só um padrão. O que importa para nós
é a segunda parte, a carga útil, que
é a parte roxa Então, aqui temos um objeto JCN
com três propriedades, sub, que é como um
ID de usuário, nome e administrador Agora, a carga útil que você vê é diferente
da carga que eu tenho porque modifiquei a pasta JS e
o webtog e
ela está Então eu gerei um token
web personalizado, coloquei-o aqui. O que eu quero
destacar aqui é que essa carga inclui
propriedades públicas sobre o usuário Assim como no seu passaporte, você tem algumas propriedades
sobre si mesmo, como seu nome,
sua data de nascimento, seu local de nascimento e assim por diante Portanto, temos exatamente o mesmo
conceito em token da web adjacente. Pode incluir algumas
propriedades públicas básicas sobre o usuário. E com isso, toda vez que
enviamos um token do
cliente para o servidor, podemos facilmente extrair o ID do
usuário da carga Se precisarmos saber
o nome do usuário
, podemos simplesmente extraí-lo
aqui também. Não precisamos
consultar o banco de dados, enviar esse ID para
obter um objeto de usuário e depois extrair
a propriedade name. Da mesma forma,
se você quiser saber se o usuário é
administrador ou não, podemos incluir isso aqui. Então, novamente, não precisamos
enviar uma consulta extra ao banco de dados para ver se o usuário com um determinado
ID é administrador ou não. Agora, você pode estar preocupado com essa abordagem do ponto de vista da
segurança, porque pode pensar que
qualquer pessoa pode simplesmente definir essa propriedade
de administrador como verdadeira
e, em seguida, será tratada
como administrador no servidor. Mas não é assim que os ptocanos de
Jason funcionam. A terceira parte
desse token JCN Web, que está em azul, é
uma assinatura digital Essa assinatura digital é
criada com base no conteúdo
deste JCN WebTken junto com
uma chave secreta ou privada A chave secreta ou privada só
está disponível no servidor. Portanto, se um usuário mal-intencionado obtiver o JCN WebTKen e modificar
a propriedade do administrador, a assinatura digital
será inválida porque o conteúdo do
JCN Agora precisamos de uma nova assinatura
digital, mas o hacker não pode gerar essa assinatura digital
porque precisará da chave privada, que só está disponível
no servidor Portanto, se eles não tiverem
acesso ao servidor, não
poderão criar uma assinatura digital
válida. E quando eles enviarem esse token JCN Web
temperado para o servidor, o servidor o recusará O servidor dirá que esse
não é um token web JCN válido. Então é assim que os tokens JCN
Web funcionam.
10. Gerando tokens de autenticação: Então, nesta página, se você
olhar as bibliotecas, aqui você encontrará
diferentes módulos ou bibliotecas para
diferentes plataformas. Então, se você rolar para baixo,
verá que Tad net one C B, C, C plus plus, node e assim por diante Então, vamos abrir o terminal
e instalar o JCN webtook e o BM e instalar o ASN Ok, se você olhar
o pacote em JSON, verá que a versão que
estamos usando é 9.0 0.2 Então, vamos fechar isso. Temos o caminho para
autenticar usuários. Agora, precisamos criar um JCN WebTken antes de enviar uma
resposta ao cliente Então, antes disso, você
precisa carregar o JCN WebTken. Então, no topo,
exija que Jason rep, engasgue e armazene em
uma constante chamada Ótimo. Agora, aqui, usaremos o método
senoidal do JWT. Portanto, JW não seno, então
aceitará dois argumentos. primeiro é a carga útil e o segundo é o rei
secreto ou privado Portanto, a carga útil pode
ser uma string simples ou pode ser um objeto como
o que você vê aqui Então, vamos criar nosso objeto
com apenas uma propriedade. Incluiremos o ID de sublinhado e o enviaremos para o ID de sublinhado de pontos
do usuário Agora, de acordo com o segundo argumento, enviaremos isso para uma string. Mas, idealmente, você não
deve armazenar sua
chave secreta ou privada em seu código-fonte. Posteriormente, mostrarei como
armazenar isso em um
ambiente onde o. Mas, por enquanto, vamos
colocar isso no segredo do JWT Não precisa
ser uma chave secreta do JWT. Pode ser qualquer coisa,
qualquer corda. Mas, por enquanto, vamos usar isso. Então, usamos um método de sinal
e, como resultado, obtemos um token. Então, vamos armazená-lo constantemente
e chamá-lo de token. E agora retornaremos ou enviaremos a resposta
ao nosso cliente como um gancho. Então, há isso de volta
ao terminal. Vamos seguir em frente. Agora, vamos ao carteiro. Aqui, enviaremos o e-mail e a senha
corretos para essa
rota de autenticação. Então, vamos enviar isso. E aqui está nosso token web JCN. Então, deixe-me copiar isso. E vamos voltar
ao depurador. Nesta seção codificada, você pode simplesmente excluir
esta e colar a
que copiamos E aqui, na seção
decodificada, você pode ver nosso objeto
que enviamos como um token, então aqui
temos a propriedade ID, que é definida como a
ID do objeto no banco de dados Mongaim Além disso,
temos o IAT, que é a hora atual e a hora em que esse token é criado Isso é usado para H do token. Portanto, criamos
o token com sucesso e o enviamos como
uma resposta ao nosso clima. No próximo vídeo,
mostrarei como incluir essa chave secreta em
uma variável de ambiente.
11. Armazenando segredos em variáveis de ambiente: No início do curso, quando eu estava falando sobre tópicos avançados do
Express, apresentei a você um
pacote de nós chamado Config Usamos esse pacote para armazenar as
configurações do nosso aplicativo em arquivos JSON
ou variáveis de ambiente Então, nesta palestra,
vamos pegar
essa chave secreta e armazená-la em uma variável de ambiente
porque, como eu disse antes,
você nunca deve armazenar seus
segredos em sua base de código Caso contrário, esses segredos serão visíveis para qualquer pessoa que tenha
acesso à sua fonte. Então, de volta ao terminal, vamos instalar o módulo de configuração Posso observar o
número da versão que é 3.3 0.11. Agora, primeiro, precisamos criar
uma nova pasta que seja config. Nessa pasta, adicionamos um arquivo de configuração padrão
que é o ponto padrão JSM Então, um objeto SN simples. Poderíamos ter várias
configurações aqui. Mas, por enquanto, eu só
quero adicionar uma configuração. Essa é a chave secreta do JWT. Agora, neste arquivo GSN padrão, vamos definir isso
como uma string vazia O valor real não está aqui. Então, aqui estamos apenas definindo um modelo para todas as
configurações em nosso aplicativo. Agora precisamos criar
outro arquivo com
variáveis de ambiente
personalizadas dot JS. Observe a ortografia,
certifique-se de acertar. Caso contrário, o que
vou mostrar
nesta palestra não funcionará
em sua máquina Então, como eu disse
antes, neste arquivo, especificamos o mapeamento entre as configurações do
nosso aplicativo
e as variáveis de ambiente. Então, vou voltar
ao nosso ponto padrão Son, copiar tudo isso e colar aqui. Portanto, essa é a estrutura do nosso objeto de configuração do aplicativo. Agora, queremos mapear
isso para uma configuração para uma variável de ambiente
chamada chave secreta JWT Mas, como prática recomendada, novamente, como eu disse antes, é melhor prefixar
isso com nome do
nosso aplicativo para que você não acabe com uma configuração do aplicativo substituindo outra configuração do
aplicativo Portanto, rodas justas alinham a chave secreta do
JWT. Agora, com isso, podemos voltar
ao nosso módulo Auth, então Js. Então, este é um lugar onde
referenciamos o segredo. Vamos
substituí-lo por uma chamada
para o método Confic dot get Então, primeiro na parte superior, precisamos
importar o objeto de configuração. Então, configuração do Cs. Definimos isso para
exigir confit. Ok. Agora, de volta ao método post, chamamos config dot cat e passamos o nome da configuração do
aplicativo Nesse caso, o segredo do JWT K.
Então, agora, isso não é um segredo. É o nome da configuração do nosso
aplicativo. O valor real,
o segredo real estará em uma variável de
ambiente. Uma última mudança, precisamos
ir para index dot js. Quando o aplicativo é iniciado, você deseja garantir que essa
variável de ambiente esteja definida. Caso contrário, teremos que
encerrar o aplicativo porque nosso endpoint de
autenticação não pode funcionar corretamente Mais uma vez, na parte superior, carregamos o módulo de configuração Config, definimos isso
para exigir configuração. Agora, mais uma vez,
vamos chamar config dot get pass o nome da chave secreta
JWT de configuração
do aplicativo Agora, se isso não estiver definido, registraremos
um erro fatal. A chave secreta do JWT não está definida. E então precisamos
sair do processo. Anteriormente, você aprende sobre
esse objeto de processo. Esse é um dos objetos
globais no node. Aqui temos um
método chamado exit. Nós lhe damos um código, zero
indica sucesso. Qualquer coisa menos zero significa fracasso. Muitas vezes, usamos exit one se você quiser sair do
processo em caso de erro. Então, atualmente, eu não configurei
essa variável de ambiente. Vamos executar o aplicativo
e ver o que acontece. Então Norman index dot JS, ok, olha, temos
esse erro fatal O aplicativo travou, aguardando alterações no
arquivo antes de começar. Agora você pode pensar que
o aplicativo
ainda está em execução porque
Norman ainda está lá Não foi encerrado. Mas se você for ao
Postman e enviar uma solicitação de SDDP para
o aplicativo, verá que nosso
aplicativo não está Então, se o aplicativo falhar, Norman ainda está trabalhando Norman ainda está correndo. Deixe-me mostrar o que quero dizer. Então, se, em vez de não modificar,
eu executar o aplicativo com o
nó, vejo que o
aplicativo travou e agora estamos de volta
ao terminal Portanto, não estamos respondendo a nenhuma solicitação recebida
dos clientes Agora, vamos definir a variável de
ambiente. Como eu disse antes, no Mac, você usa Export, no Windows, você usa set para prompt de
comando e coluna dollar
ENV para Power Shell Coluna Dollar ENV, rodas justas,
sublinhado, chave secreta da JWT.
Nós definimos isso também. Digamos que minha chave segura. Agora vamos executar o
aplicativo novamente. Índice de nós ou Js.
Ok, lindo. Nós o conectamos ao
Mongadib e, se
voltarmos ao Postman e enviarmos
outra solicitação ao Login, aqui está nosso cheese válido e token
da web que são assinados
com nossa chave secreta,
que é armazenada em
12. Definindo cabeçalhos de resposta: Portanto, na
implementação atual, quando o usuário faz login, geramos um token web JCN e o retornamos no
corpo da resposta Agora, vamos levar esse
aplicativo para o próximo nível. Vamos imaginar que, quando
o usuário se registra, queremos supor
que ele esteja logado, para que ele não precise fazer
login separadamente Obviamente, esse requisito
não se aplica a todos os aplicativos. Às vezes, você quer obrigar o usuário a verificar
seu endereço de e-mail Então, depois que eles se inscreverem, você envia um e-mail e eles
clicam em um link. Portanto, o processo é diferente. Mas neste curso, vamos
imaginar que o Fair Wheels seja um aplicativo executado
localmente em uma locadora de veículos. Portanto, as pessoas que usam esse aplicativo são pessoas
que trabalham nesse aluguel de carros. Não precisamos verificar o endereço de e-mail
deles. Então, no primeiro dia em
que
entram na loja, precisam criar uma conta e pronto, estão logados Então, vamos ao módulo
do nosso usuário. Ok, aqui está o método de postagem. É aqui que
registramos um novo usuário. Agora, se você observar a
resposta que estamos retornando aqui, estamos retornando um objeto
com essas três propriedades. Agora podemos adicionar o
token web JCN como outra propriedade aqui, mas isso é um pouco feio porque não é
propriedade de um Uma abordagem melhor é retornar o token web JCN
em um cabeçalho SDDP Assim como temos
cabeçalhos em nossa solicitação, também
temos cabeçalhos em
nosso objeto de resposta Então, vou voltar ao nosso módulo Auth e emprestada essa linha de código
para gerar o token Então, copie isso agora
de volta para o módulo do usuário. Antes de enviarmos a
resposta ao cliente,
geramos o token e seguida, chamamos um cabeçalho de ponto de
resposta. Com isso, podemos definir um cabeçalho. Agora, para qualquer cabeçalho personalizado que definimos em
nosso aplicativo, devemos prefixar
esses cabeçalhos com X. Agora, damos a ele um nome
arbitrário que definimos em
nosso aplicativo,
devemos prefixar
esses cabeçalhos com X.
Agora, damos a ele um nome
arbitrário, como autenticação ou token. Esse é o primeiro argumento, que é o nome do cabeçalho. O segundo argumento
é o valor,
que, nesse
caso, é nosso token. Então, com essa mudança simples, definimos esse cabeçalho e enviamos essa resposta
ao cliente. Está bem? Agora, na linha 20, estamos usando o JWT, bem
como o módulo confit Então, precisamos
importá-los na parte superior. Então, um TWT constante, configuramos isso
para exigir o token web JCN. E da mesma forma, configuração constante, definimos isso para exigir confit Agora vamos testar isso. Então,
na última aula, executei o aplicativo com
node em vez do modo nor Portanto, minhas alterações não são visíveis. Portanto, precisamos parar o
aplicativo e executá-lo com o modo de
nó. Ok, lindo. Agora, de volta ao Postman aqui nesta guia para
registrar um usuário, vou mudar esse e-mail
para um e-mail que eu
não tenha registrado Enviado. Ok, dê uma olhada. Então, aqui está o corpo da
resposta exatamente como antes. Agora, na aba Headertab Look, temos esse novo
cabeçalho, o token X. E isso está configurado para o
nosso JCN WebTken. Então, em nosso aplicativo cliente, quando registramos um usuário, podemos ler esse cabeçalho. Podemos armazenar esse JCN
WebTgen no cliente. E da próxima vez que
fizermos uma chamada de API, enviaremos isso para o servidor.
13. Encapsulando a lógica em modelos Mongoose: Agora, há um problema em
nossa implementação atual. No módulo do usuário na linha 22, é
assim que geramos
um token web JCN Temos exatamente o mesmo núcleo
no módulo Auth na linha 20. Agora, veja a carga útil desse token
da web JCN. Nessa carga, atualmente, temos apenas a propriedade ID Provavelmente, amanhã
adicionaremos
outra propriedade a esse pagamento,
talvez o nome do usuário, talvez seu endereço de e-mail,
talvez sua função. Queremos saber se
há um usuário administrador ou não. Com a implementação atual, toda vez que quisermos
alterar essa carga, precisamos lembrar
que precisamos ir para outro módulo e fazer exatamente
a mesma alteração E, a longo prazo, você esquecerá
esses requisitos. Então, nesta palestra,
vou mostrar como encapsular essa
lógica em um Agora, para onde devemos
mover essa lógica? Um programador amador
pode pensar: Ok, vou criar uma função como gerar token de
autenticação, colocar essa função em algum lugar
que possamos reutilizar, talvez em outro
módulo que possamos importar nos módulos da Terra
e do usuário E com isso, temos a
lógica em um único lugar. Bem, isso é verdade. Isso funciona. Mas com essa abordagem, você acabará com muitas funções espalhadas por
todo o lado. Na programação orientada a objetos, temos um princípio chamado princípio do especialista em
informações. Isso significa um objeto que tem informações
suficientes e é
especialista em uma determinada área. Esse objeto deve
ser responsável por tomar
decisões e
executar tarefas. Como exemplo do mundo real,
pense em um chef. Um chef tem
conhecimento de culinária. É por isso que o ato de cozinhar em um restaurante é feito por um
chef e não por um garçom O garçom não tem
o conhecimento certo, as informações certas sobre
culinária em um restaurante Então, se o chef é um objeto, devemos dar o ato
de cozinhar ao chef. Agora, pegue esse princípio
e aplique-o neste código. Então, aqui, como parte da criação
desse token Chase e da web, o que precisamos na carga útil Precisamos do ID do usuário. Amanhã, talvez precisemos do nome do usuário
ou do e-mail dele. Então, todas essas informações estão encapsuladas aqui
no objeto do usuário Portanto, é o
objeto do usuário que deve ser responsável por gerar
esse token de autenticação. Então, a função
que eu escrevi aqui, gerar token de autenticação, essa função não deve estar pendurada
em algum lugar em um módulo. Isso deve ser um método
no objeto do usuário. Então, aqui temos um objeto de usuário que carregamos do banco de dados. Precisamos adicionar um método
nesse objeto de usuário como esse. Usuário que gera o token
de autenticação. E isso nos dará uma
lembrança, simples assim. Agora, como podemos adicionar isso? Precisamos acessar nosso
módulo de usuário, onde definimos o modelo do usuário e fazemos uma alteração
simples nele. Tudo bem Então, aqui em nosso modelo de usuário, precisamos extrair a definição
desse esquema e
colocá-la em uma constante separada porque vamos
trabalhar com esse esquema separado Então, vou
selecionar todo esse código. Portanto, ao criar o
modelo do usuário como segundo argumento, passamos o esquema do usuário e ainda não o
criamos Nós vamos fazer isso agora. Então, esquema de usuário constante, e definimos isso para essa
expressão assim Ok. Então, aqui está nosso esquema de usuário Agora, você deseja adicionar um
método nesse esquema. Então, o esquema do usuário em que
temos uma propriedade, métodos, isso retorna um objeto Podemos adicionar mais pares de
valores-chave nesse objeto. Assim, podemos adicionar uma chave, gerar
autenticação ou token. Definimos isso como uma função.
Então, par de valores-chave. Quando fizermos isso, nosso objeto de
usuário terá um método chamado generate
authentication token. Agora, aqui, nesta função, podemos ter parâmetros. Então, se tivermos um parâmetro aqui, ao chamar esse método, podemos passar argumentos. Nesse caso, não
precisamos de nenhum parâmetro, então eu só preciso pegar essa lógica para
gerar o token, obtê-lo daqui e
movê-lo dentro desse novo método. Então, aqui na carga, precisamos do D do
usuário. Como podemos conseguir isso? Bem, esse método fará
parte do objeto do usuário. Então, para referenciar
o objeto em si, substituímos o usuário por isso. E isso significa que aqui você deve usar a sintaxe da
função regular Você não pode substituir isso
por uma função de seta. Porque, como eu disse antes, as funções de
seta não
têm nada a ver com isso. Isso em uma
função de seta faz referência
à função de chamada. Então, normalmente, usamos seta para funções
autônomas Se você quiser criar um método
que faça parte de um objeto, você não deve usar
uma função de seta. Agora, vamos reverter isso. Então, aqui temos o token
e, finalmente, o
devolvemos tão simples quanto isso. Aqui estamos fazendo referência ao
JWT e aos módulos de conflito. Então, precisamos importar
isso na parte superior. Então, vou voltar ao
nosso módulo Auth na parte superior. Não precisamos mais dessas declarações
obrigatórias. Então, eu vou
pegá-los daqui. E coloque-os em cima
do módulo do usuário. Agora, de volta ao módulo de
autenticação
, geramos o token e
o enviamos para o cliente. Precisamos fazer as mesmas
alterações no módulo do nosso usuário. Módulo do usuário,
excluímos essa linha e definimos o token para o usuário
que gera AuthToken Então, finalmente, vamos testar isso e garantir que
tudo esteja funcionando. Então, vou registrar
um novo usuário aqui. Envie, linda. E aqui está nosso token
de autenticação.
14. Middleware de autorização: Portanto, no início
desta seção, decidimos proteger
as operações que modificam os dados e os
disponibilizam somente para usuários
autenticados Então, vamos até nossas empresas, Dot CHASE Piers, o método de postagem
para criar uma nova empresa Esse endpoint da API só deve ser chamado por um usuário
autenticado. Então, como podemos impor isso? Bem, aqui, fizemos
uma lógica como essa. Precisamos ler os cabeçalhos da
solicitação. Portanto, esse objeto de solicitação tem
um método chamado header. Aqui, especificamos o
nome do cabeçalho, que é o token X. Esperamos um token web JCN
armazenado nesse cabeçalho. Então, armazenamos isso
como um token constante. Agora, queremos validar isso. Se isso for válido,
concederemos acesso a
esse endpoint da API Caso contrário, retornaremos
uma resposta como essa. Resposta para o
código de status de quatro em um, que significa que o
cliente não tem as credenciais de autenticação
para acessar esse recurso Então esse é o panorama geral. Agora, não queremos
repetir essa lógica
no início de cada
manipulador de rotas que modifica dados Então, precisamos colocar essa lógica
em uma função de middleware. Lembre-se,
funções de middleware, falamos sobre elas na seção chamada Tópicos avançados do
Express Então, colocamos essa lógica em
uma função de middleware
e, em seguida, podemos aplicar
essa função em manipuladores de
rotas que precisam
modificar dados. Deixe-me te mostrar. Então, vamos tirar isso daqui. Tudo bem, aqui queremos adicionar uma nova pasta chamada middleware Então, colocamos todas as nossas funções de
middleware aqui. Nessa pasta, tínhamos
um novo arquivo t dot tem. Agora, aqui queremos
definir uma função chamada OT que usa três parâmetros, resposta de
solicitação e next, que usamos para passar o controle para
a próxima função de middleware no pipeline de
processamento de solicitações Se esse conceito parecer
estranho para você,
você precisa voltar
para a seção chamada Express Advanced Topics, pois lá exploramos
as funções de middleware Então, aqui nesta função, devemos implementar essa
lógica. Nós recebemos o token. É provável que não
tenhamos nenhum token. Nesse caso, retornamos uma resposta 41 com uma
mensagem como essa. Acesso negado. Nenhum token fornecido. Portanto, isso ajuda o
cliente a
descobrir por que ele não pode
acessar esse recurso. Agora, caso contrário,
há um token. Precisamos verificar se
esse é um token válido. Então, aqui precisamos usar
nosso módulo de token JCN Web. Então, no topo, vamos exigir o
token web JCN e armazená-lo no JW Agora, aqui chamamos jwt dot Verifi. Como primeiro argumento,
passamos o token
e, como segundo argumento, passamos a chave secreta
para decodificar esse token Então, armazenamos essa chave secreta
em uma variável de ambiente. Precisamos usar um
módulo de configuração para lê-los. Portanto, exija a configuração
e guarde-a aqui. Então, assim como antes,
chamamos config dot
g JWT Ccret key. Agora, esse método de verificação
verificará Se for válido, ele o
decodificará e retornará a carga útil. Então, aqui temos a carga
decodificada. No entanto, se esse
token não for válido, ele lançará uma exceção. Portanto, precisamos envolver essa linha
com um bloco try cache. Então, experimente o Cache,
temos uma exceção. Se chegarmos aqui, queremos dizer
ao cliente que esse
é um token inválido Definimos esse status como 400 porque há uma solicitação inválida porque o que o cliente nos envia não
tem os dados corretos. Portanto, envie um token inválido. Novamente, com essa mensagem de erro, podemos solucionar os problemas de
autenticação Portanto, se no cliente não conseguirmos acessar um determinado endpoint da API, veremos a mensagem de erro Percebemos que enviamos
um token inválido. Em seguida, analisaremos a lógica
do cliente em que obtemos o token e o
enviamos para o servidor. Então esse é o nosso bloco de cache. Agora, de volta ao bloco triplo, aqui temos a folha de pagamento Então, podemos colocar isso
na solicitação. Então, nosso objeto de solicitação, adicionamos a propriedade do usuário a ele e a definimos para essa decodificação Então, anteriormente, colocamos somente o ID do
usuário na carga Deixe-me te mostrar. Então,
vamos ao nosso módulo de usuário. Aqui está o esquema do nosso usuário. Adicionamos esse método de geração
de token de autenticação. Criamos o JCN WebTken
e essa é a nossa carga útil. Então, quando decodificamos esse JWT, esse é o objeto que obteremos E vamos colocar isso na
solicitação como um objeto de usuário. Portanto, em nosso manipulador de rotas, podemos acessar request dot
user dot underline
dot ID e Está bem? Então, no bloco tri, definimos request dot user
e, em seguida, precisamos passar o controle
para
a próxima função de middleware no pipeline de processamento de solicitações Nesse caso, esse é o nosso
manipulador de rotas. Então, ligamos em seguida. Então, como eu disse antes,
nas funções de middleware, encerramos o
ciclo sl de resposta da
solicitação ou passamos o controle para a
próxima Agora, apenas um pequeno
problema nesse código, caso não
tenhamos um token, enviaremos essa
resposta ao cliente. Mas quero ter certeza de que
saímos dessa função. Tudo bem, terminamos com
nossa função de middleware. Agora, no final, configuramos as exportações de pontos do
módulo para OTO, um atalho para isso
é configurá-lo aqui Então, definimos as exportações de pontos do módulo, configuramos isso como uma função. Não precisamos de um em aqui. E então podemos nos
livrar da linha 17. Feito.
15. Protegendo rotas: Então, agora que temos uma função de
middleware, podemos ir para index dot JS,
olha, aqui estamos aplicando funções de
middleware Portanto, podemos adicionar isso aqui
e, em seguida, ele será executado
antes de cada manipulador de rotas Mas não queremos
fazer isso porque nem todos os endpoints da API
devem ser protegidos Alguns de nossos endpoints de API
devem ser públicos, como registrar
um usuário, fazer
login ou obter a lista de
empresas ou clientes Portanto, nesse caso,
queremos aplicar essa função de middleware seletivamente a Então, voltando ao módulo da empresa, aqui está nosso gerenciador de rotas de postagem O primeiro argumento é uma rota. O segundo é
opcionalmente o middleware
e o terceiro será o
verdadeiro manipulador de rotas Então, vamos ao topo, transmitir essa função de middleware
. Então exija. Agora precisamos subir um
nível e depois ir para a pasta
do middleware e
carregar o módulo Earth Nós pegamos e colocamos aqui. E finalmente, aqui
no método post,
passamos a OT como uma função de middleware a ser
executada antes dessa outra função de
middleware,
que é, neste caso, Então, agora vamos testar
isso de volta no Postman. Vou abrir uma nova guia e
enviar uma solicitação de postagem para
o endpoint da empresa Então, hospedeiro local do STDP, empresas de
API. Agora, nesse caso, não estou preocupado com o
corpo da solicitação. Só quero saber se podemos chamar esse endpoint da API ou não Então envie Ok, olha, temos esse erro 401 ou
não autorizado E aqui está a mensagem de erro. Acesso negado, Noto pode fornecer. Agora, vamos fornecer
um token inválido. Então, vamos para a guia de cabeçalhos, definimos a chave que é o token X. Eu coloquei um token inválido, enviei, recebemos 400 ou uma
solicitação inválida com esta mensagem Token inválido.
Linda. Agora, finalmente, vamos voltar ao nosso
registro, use uma guia. Temos um token de
autenticação válido. Então, vamos copiar isso de
volta para a terceira guia. Coloque-o aqui e depois envie. Ok, agora recebemos uma solicitação incorreta, mas isso não é por causa
da autenticação. Isso ocorre porque esperávamos a propriedade name
no corpo da solicitação. Então, se eu adicionar um
objeto JSON aqui
no corpo, nomeie uma nova empresa Agora, devemos estar bem. Enviar.
Então, recebemos uma resposta de 200, e esta é a nova empresa. Então, como exercício, quero que você aplique essa função de
middleware a outros manipuladores de rotas
que
16. Obtendo o usuário atual: Em muitos aplicativos, às vezes
precisamos obter informações sobre o usuário
atualmente conectado Então, nesta palestra,
vamos adicionar um novo endpoint de API para
obter o usuário atual Então, vamos ao nosso módulo de usuários. Atualmente, temos apenas
um manipulador de rotas. Isso é para criar um novo usuário. Agora precisamos adicionar outro
manipulador para obter métodos. Agora, aqui, adicione um caminho ou rota. Podemos passar um parâmetro, mas isso significa que o cliente deve enviar o
ID para o servidor. Embora essa abordagem
seja perfeitamente adequada, às vezes, talvez
por motivos de segurança, você não queira
ter um endpoint como esse, porque então eu
posso enviar a ID de outro usuário e ver a
conta dele, onde pode
haver algumas informações que talvez não devessem
estar visíveis para mim Portanto, a abordagem que usamos com
bastante frequência para obter
informações sobre o usuário atual é ter
um endpoint de API como eu Com isso, o cliente não
enviará o ID do usuário. Nós o obtemos da fonte JCN Web. Portanto, não posso falsificar JCN WebTken de
outra pessoa porque eu disse que
, para fazer isso, preciso criar uma
nova assinatura
digital para o JCN WebTken de
outra pessoa
porque eu disse que
, para fazer isso,
preciso criar uma
nova assinatura
digital para esse JCN WebTken. Então, vamos adicionar o manipulador de rotas, solicitação
assíncrona e a resposta
vão para esse bloco Agora, esse endpoint da API
só deve estar disponível para usuários
autenticados. Então, aqui precisamos adicionar
nosso middleware de OT. Na parte superior, vamos carregar o
OT a partir do middleware Auth. Só para esclarecer, aqui, autor
representa autorização,
não autenticação, porque a autenticação trata de validar
a senha do nome de usuário Aqui, queremos ver se o usuário tem permissão para acessar
um recurso ou não, e isso é autorização. Adicionamos nosso middleware aqui. Agora, com esse middleware, se um cliente não enviar um token web JCN
válido, nunca
chegaremos a
esse No entanto, se você chegar aqui, como viu na
implementação
dessa função de middleware aqui, teremos request
dot user object Assim, podemos acessar a propriedade
ID aqui. Então, em vez de passar a propriedade ID no
caminho ou na rota,
nós a obtemos da solicitação
dot user dot ID, que na verdade
vem do nosso token web JSON Portanto, essa é uma abordagem mais segura. Agora, queremos encontrar um
usuário pelo ID fornecido. Então, chamamos o usuário dot fine por ID. Pré-passe esse valor
, aguarde a promessa e
obtenha o objeto do usuário aqui Agora, não queremos devolver a senha do usuário
ao cliente. Então, aqui, vamos chamar Selecionar e excluir a propriedade da
senha. Em seu aplicativo, talvez você também queira excluir outras
propriedades. Talvez endereço,
talvez número de telefone. Então, aqui temos um objeto de usuário. Finalmente, enviamos
isso para o cliente. Então, envie ao usuário de forma tão simples quanto
isso. Agora, vamos testar isso. Então, aqui no Postman, vou adicionar uma nova guia,
enviar uma solicitação Get para o
host local para 3.000 usuários da API para Agora, inicialmente, eu não
quero enviar um JCN WebTken. Portanto, envie Xs negados sem token,
fornecido. Linda. Agora vamos para a guia de cabeçalhos. Adicione X ou token aqui
e, em seguida, passe um
queijo casado e um token web SN. Esta é minha conta de usuário. Podemos ver que a senha está excluída.
17. Desconectando usuários: Então, em nosso módulo Auth, definimos essa rota para
autenticar usuários Que tal desconectar usuários? Precisamos de uma
rota separada para isso? Não, porque não estamos armazenando esse token
em nenhum lugar do servidor. Portanto, não precisamos de um manipulador de rotas
separado para excluir esse token Então, tecnicamente, você
precisa implementar o recurso de desconexão no
cliente, não no servidor Portanto, no aplicativo cliente, quando o usuário quiser sair, basta excluir esse
token do cliente. Agora, eu vi cursos
e tutoriais que ensinam você a armazenar esse token no servidor no banco Essa é uma prática muito ruim
porque esses tokens são como chaves que dão ao cliente acesso a endpoints de API protegidos Se um hacker conseguir
acessar seu banco de dados, ele poderá ver todos esses tokens
para usuários autenticados Eles nem precisam saber
a senha de um usuário. Eles podem simplesmente obter
seu
token de autenticação e enviá-lo
ao servidor para executar a
solicitação em nome de um usuário. Você não deve armazenar
tokens em seu banco de dados. E se você sabe
o que está fazendo e realmente deseja armazenar
o token no banco de dados, certifique-se de criptografá-lo.
Certifique-se de fazer um hash. Assim como as senhas. Armazenar um token em
um texto simples no banco de dados é como obter o passaporte ou a
carteira de motorista de todos os usuários, colocá-los em um
local central e, em seguida,
qualquer usuário mal-intencionado que tenha
acesso a esse local central pode simplesmente obter
esses passaportes Eles podem obter essas
carteiras de motorista e imitar outros
usuários, outros clientes Então, mais uma vez, não armazene
os tokens no servidor, armazene-os no cliente. E como prática recomendada de segurança, sempre que você estiver
enviando o token do cliente para o servidor, certifique-se de usar HTTPS. Portanto, um hacker sentado no
meio do tráfego não consegue ler o token
enviado do cliente
para o servidor,
então os dados são criptografados
entre o cliente
e o
18. Autorização baseada em funções: Até agora,
implementamos a autenticação e a autorização com sucesso. Agora vamos levar esse
aplicativo para o próximo nível. Vamos imaginar que certas
operações, como excluir dados, só possam
ser realizadas por administradores Então, deixe-me mostrar como
implementar uma autorização
baseada em funções. Primeiro, precisamos
acessar nosso modelo de usuário. Portanto, esse é o nosso esquema de usuário. Atualmente, temos
três propriedades, nome, e-mail e senha. Agora, precisamos adicionar
outra propriedade para ver se um determinado usuário
é administrador ou não. Então, vamos adicionar uma nova propriedade
admin do tipo Boolean. Então esse é o primeiro passo. Agora vou entrar
no Mongo DB Compass, pegar um desses usuários e
torná-lo administrador. Então edite. Vou adicionar um
campo após a senha, e a ordem
realmente não importa. O mesmo acontece com admin e, por padrão, você pode ver que o
tipo disso é string. Vamos mudar
isso para Boolean. Então, vamos dizer que isso é verdade e , finalmente, aplicar a atualização. Então, aqui eu tenho um usuário
que é administrador. Agora, ao fazer o login,
quero incluir essa propriedade em nosso payload do
JSON Web Token Então, da próxima vez que eles enviarem esse
JCN WebTken para o servidor, poderemos extrair essa propriedade
diretamente do Não precisamos obter o ID, entrar no banco de dados e ver
se eles são administradores ou não. E, novamente, como eu disse antes, com a assinatura digital
incluída em um webtken da JCN,
um usuário mal-intencionado não pode alterar o valor de seu administrador
para sua conta Se eles fizerem alguma alteração, precisarão regenerar
a assinatura digital, e isso requer
conhecer a chave privada que armazenamos em uma
variável de ambiente no servidor Agora, de volta ao nosso módulo de usuário, quando geramos o token de
autenticação, queremos adicionar essa
propriedade na carga Então, aqui está nossa carga útil. Vamos adicionar uma nova propriedade
como administrador. Nós configuramos isso para. Esse dt é Admin. Portanto, esse é o benefício de encapsular essa lógica
dentro do objeto do usuário Portanto, há um único lugar
que precisamos modificar. Anteriormente, tínhamos isso
em dois lugares diferentes. E com essa mudança de símbolo, tivemos que lembrar de aplicar essa alteração em dois
lugares diferentes no código. Então esta é a nossa joelheira. Agora, no servidor, precisamos uma nova
função de middleware para verificar se o usuário atual é
administrador ou Então, aqui na pasta de
middleware, vou adicionar um
novo arquivo, admin Então, aqui configuramos o módulo que exporta para uma função de
middleware E recebe uma solicitação, uma resposta e uma referência à
próxima função de middleware no pipeline de
processamento de solicitações Então, aqui estamos assumindo que
essa função de middleware
será executada após
nossa função será executada após de middleware de autorização Portanto, nossa função de
middleware de autorização define solicitação, não o usuário, para que possamos acessá-la
nesta Então, solicito que o
usuário que é administrador, ou digamos que,
se ele não for administrador, retornaremos o status de
resposta. Definimos o status 24 em
três, o que é proibido. Essa é uma das áreas em que muitos desenvolvedores erram. Então, temos 41, o que significa não autorizado, e
temos quatro e três,
o que significa proibido Usamos não autorizado quando o usuário tenta acessar
um recurso protegido, mas ele não fornece
um JSN WebKen válido Então, damos a eles
a chance de tentar novamente e enviar um JCN WebKen válido agora Se enviarem um token web GSN
válido e ainda não tiverem permissão para acessar o recurso de destino, é quando usamos
quatro e três, o
que significa proibido, o que
significa não tente novamente, simplesmente não
podemos acessar
esse que significa proibido, o que
significa não tente novamente, simplesmente não podemos Então, aqui, definimos o status e enviamos uma
mensagem como acesso negado. Agora, caso contrário, se
o usuário for administrador, passaremos o controle para a
próxima função de middleware, que é, nesse caso,
o manipulador de rotas Agora vamos aplicar essa função de middleware
em uma de nossas rotas. Então, voltando às empresas dot JS, vamos dar uma olhada no método delete. Então, aqui está nosso método de exclusão. Queremos aplicar duas funções de
middleware aqui. Então, precisamos passar uma matriz. O primeiro é OT e
o segundo é administrador. Portanto, essas funções de middleware serão executadas em sequência Primeira parte, se o cliente
enviar um Jas variado no webtken, depois
chegaremos à segunda função de
milware O usuário é administrador e, em
seguida, a terceira função de
middleware ou manipulador de rotas
será executada Agora, precisamos importar
isso no TA. Portanto, como administrador constante,
configuramos isso para
exigir que você acesse a pasta do
middleware e carregue o módulo de administração Agora, vamos testar isso.
De volta ao Postman Vou abrir
uma nova guia e enviar
uma solicitação de exclusão
para esse endpoint, host local
STDP para
3.000 Agora, deixe-me pegar uma identificação de uma empresa do banco de dados
Mongo IV. Então vá para Companies
Collection, aqui, copie esse ID e coloque-o em
nosso endpoint desta forma Não se esqueça de
incluir o token de probabilidades. Caso contrário, você receberá
o erro de autorização. Excesso negado, nenhum
token o fornece. Então, vamos colocar o token
e agora enviá-lo. Linda. Temos
uma resposta de 200, e aqui está a empresa
que foi excluída.