Sistema de autenticação Vue.js com back-end Node.js

Blog

Sistema de autenticação Vue.js com back-end Node.js

Neste tutorial, vamos explorar diferentes tipos de autenticação para aplicativos JavaScript e construir um sistema de autenticação Vue com um Node.js ...



Ao construir um Vue.js sistema de autenticação, há dois cenários principais envolvidos. Cenário um: uma parte controla o front-end e o back-end; cenário dois: um terceiro controla o back-end. Se for o último caso, temos que adaptar o front-end. Ele precisa lidar com qualquer tipo de autenticação disponível no back-end.

O código finalizado para este tutorial está disponível nestes repositórios GitHub:



Tipos de autenticação de JavaScript de front-end

Em nosso aplicativo, temos a flexibilidade de escolher entre vários tipos de autenticação. Isso ocorre porque seremos responsáveis ​​pelo front-end e pelo back-end. Vamos identificar os dois tipos. O primeiro é local ou mesmo domínio autenticação - este é o caso quando o front-end e o back-end estão rodando no mesmo domínio. O segundo é domínio cruzado autenticação - é quando o front-end e o back-end são executados em domínios diferentes.

transferência de app de dinheiro falhou

Estas são as duas categorias principais, mas há muitas subcategorias nelas. À luz do acima, vamos usar local autenticação uma vez que somos responsáveis ​​por todo o sistema. Estaremos usando muitos Node.js bibliotecas. Mas os dois principais são Passport.js e Express.js . Passport.js é uma biblioteca de autenticação. Ele fornece vários recursos como local autenticação, Autenticação OAuth e Autenticação de logon único . Express.js é uma estrutura de servidor para Node.js usado para construir aplicativos da web.



O paradigma do aplicativo

Nosso aplicativo front-end terá duas páginas principais: uma página de login e uma página de painel. Usuários autenticados e anônimos terão acesso à página de login. A página do painel só estará acessível para usuários autenticados. A página de login terá um formulário que enviará dados por meio do Ajax para nossa API back-end. Em seguida, o back-end verificará se as credenciais estão corretas e responderá ao front-end com um cookie. Este cookie é o que o front-end usará para obter acesso a quaisquer páginas bloqueadas.

A revalidação do cookie acontece em cada solicitação para uma página bloqueada. Se o cookie se tornar inválido ou o usuário não estiver conectado, ele não poderá acessar o painel. O back-end enviará uma resposta de erro e o front-end saberá como redirecionar o usuário de volta para a página de login.

Não configuraremos um banco de dados real - usaremos uma série de usuários no back-end para simular alguma forma de banco de dados. Finalmente, teremos um link de logout. Isso enviará uma solicitação ao nosso servidor para invalidar nossa sessão atual e, portanto, desconectar o usuário atual.

Então, vamos começar a construir nosso Vue.js sistema de autenticação usando Node.js como back-end.

Configuração do front-end do Vue.js

Para começar, primeiro precisamos ter a versão mais recente do Node.js e vue-cli configurar. No momento deste artigo, a versão mais recente do vue-cli é a versão 3. Se a versão instalada for 2, queremos atualizar - primeiro precisamos remover a versão antiga executando:

npm uninstall vue-cli -g

Em seguida, instale a versão mais recente executando:

npm install -g @vue/cli

seguido pela

npm install -g @vue/cli-init

Depois de configurar o acima, vá para qualquer pasta no terminal e execute:

vue init webpack vueauthclient

Isso criará um novo aplicativo em vueauthclient usando o webpack organização de pastas.

Devemos obter alguns prompts na linha de comando. É seguro selecionar todos os padrões - mas, para este artigo, podemos selecionar não para os testes. Em seguida, navegue até esta pasta usando cd vueauthclient e execute o aplicativo usando:

npm run dev

Isso iniciará um servidor de desenvolvimento que pode ser acessado no URL localhost:8080. Depois de visitar este URL, o logotipo Vue.js com algum texto deve estar visível na página. O Vue.js componente responsável por exibir esta página reside no arquivo:

vueauthclient/src/components/HelloWorld.vue

Tela de login principal

Deixe-nos configurar nossa página de login. Então, vamos mudar a página inicial para o padrão para a tela da página de login que ainda estamos para criar. A partir de agora, deixaremos de fora a pasta principal do aplicativo vueauthclient, ao fazer referência aos arquivos.

Vamos instalar a biblioteca Ajax chamada Axios usando:

npm install axios --save

Esta é uma biblioteca que torna mais fácil fazer chamadas HTTP Ajax para qualquer servidor back-end. Ele está disponível para aplicativos front-end e back-end, mas aqui, vamos usá-lo apenas no front-end.

Em seguida, crie um arquivo de componente de login em src/components/Login.vue. Neste arquivo, cole o seguinte:

Login



import router from '../router' import axios from 'axios' export default { name: 'Login', methods: { login: (e) => { e.preventDefault() let email = 'user@email.com' let password = 'password' let login = () => { let data = { email: email, password: password } axios.post('/api/login', data) .then((response) => { console.log('Logged in') router.push('/dashboard') }) .catch((errors) => { console.log('Cannot log in') }) } login() } } }

Vamos analisar esse código para ver o que está acontecendo.

A parte do modelo abaixo é um formulário com dois campos de entrada: email e password. O formulário tem um submit manipulador de eventos anexado a ele. Usando o Vue.js sintaxe v-on:submit='login', isso enviará os dados do campo para o login método de componente.

Login



Na parte do código do script, conforme mostrado abaixo, estamos importando nosso arquivo do roteador. Este reside em src/router/index.js. Também estamos importando o Axios biblioteca ajax para o front-end. Então, estamos armazenando as credenciais do usuário e fazendo uma solicitação de login ao nosso servidor back-end:

import router from '../router' import axios from 'axios' export default { name: 'Login', methods: { login: (e) => { e.preventDefault() let email = 'user@email.com' let password = 'password' let login = () => { let data = { email: email, password: password } axios.post('/api/login', data) .then((response) => { console.log('Logged in') router.push('/dashboard') }) .catch((errors) => { console.log('Cannot login') }) } login() } } }

Na área de script abaixo,

como atualizar as janelas do node.js
e.preventDefault() let email = '[user@email.com](mailto:user@email.com)' let password = 'password'

Estamos armazenando nome de usuário e senha embutidos em variáveis ​​por enquanto. Isso ajuda a acelerar o desenvolvimento, impedindo-nos de redigitar a mesma coisa. Mais tarde, vamos trocá-los e obter os dados reais do envio do formulário.

Na parte final do código abaixo, estamos fazendo uma chamada ajax usando as credenciais acima. No caso de um ok resposta do servidor, redirecionamos o usuário para o painel de controle . Se a resposta não for ok, permaneceremos na mesma página e registraremos um erro no console.

let login = () => { let data = { email: email, password: password } axios.post('/api/login', data) .then(response => { console.log('Logged in') router.push('/dashboard') }) .catch(errors => { console.log('Cannot login') }) } login()

Agora que configuramos nosso componente de login, vamos mudar o roteador para garantir que ele reconheça a nova página. No arquivo src/router/index.js, altere o roteador existente para este:

import Vue from 'vue' import Router from 'vue-router' import Login from '@/components/Login' import HelloWorld from '@/components/HelloWorld' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld }, { path: '/login', name: 'Login', component: Login } ] })

O que fizemos é importar nosso novo componente e, em seguida, adicionar um objeto à matriz de rotas. Remova o registro de rota HelloWorld, pois não precisaremos mais dele.

Finalmente, para a página de login, vamos ter certeza de que é a página padrão de nosso aplicativo. Altere o caminho atual do registro da rota de login de

path: '/login',

para

path: '/',

Não se esqueça de excluir o registro da rota para a rota HelloWorld, caso contrário, pode ocorrer um erro. Navegando para localhost:8080 novamente no navegador, devemos ver nosso novo formulário de login. Enviá-lo nesta fase não fará nada, exceto reclamar que o URL de back-end localhost:8080/api/login não existe.

Configuração da primeira página segura - o painel

Agora na página do painel. Crie um componente para ele criando um arquivo em src/components/Dashboard.vue. Lá, cole o seguinte:

Dashboard

Name: {{ user.name }}

import axios from 'axios' import router from '../router' export default { name: 'Login', data() { return { user: { name: Jesse } } }, methods: { getUserData: function() { let self = this axios.get('/api/user') .then((response) => { console.log(response) self.$set(this, 'user', response.data.user) }) .catch((errors) => { console.log(errors) router.push('/') }) } }, mounted() { this.getUserData() } }

Na seção de modelo, estamos exibindo o nome de usuário atual. Antes de configurar o back-end, iremos codificar um usuário no front-end. Isso é para que possamos trabalhar com esta página ou obteremos um erro.

Na seção de script, estamos importando Axios biblioteca e nosso roteador. Então, temos uma função de dados para nosso componente onde retornamos um objeto com uma propriedade do usuário. Como podemos ver, atualmente temos alguns dados do usuário codificados.

Também temos dois métodos chamados getUserData e mounted. o Vue.js motor chama o mounted método quando o componente é aberto. Nós só temos que declarar isso. O segundo método, getUserData é chamado no mounted método. Lá, estamos fazendo uma chamada para o servidor back-end para buscar os dados do usuário conectado no momento.

Durante a chamada para o back-end, obtemos uma resposta do servidor. Teremos que lidar com dois cenários possíveis, dependendo do tipo de resposta.

Primeiro, se a chamada foi bem-sucedida, definimos a propriedade do usuário com os dados retornados do back-end usando:

self.$set(this, 'user', response.data.user)

Em segundo lugar, se houver um problema de login, o servidor responde com um erro. Em seguida, o front-end redireciona o usuário de volta para a página de login com esta linha:

router.push('/')

Usamos o push método acima para redirecionamento e está disponível no pacote chamado vue-router, o roteador padrão para Vue.js . Vamos adicionar a configuração de rota para esta página, adicionando-a ao arquivo de rota, como fizemos para a página de login. Importe o componente:

import Dashboard from '@/components/Dashboard'

E adicione a definição de rota:

{ path: '/dashboard', name: 'Dashboard', component: Dashboard }

Configurar camada de dados front-end com Axios

Agora que temos nossas páginas de front-end no lugar, vamos configurar Axios e Vue.js . Vamos deixá-los prontos para se comunicarem com nosso back-end. Como estamos na fase de desenvolvimento, o front-end está sendo executado na porta 8080. Assim que começarmos a desenvolver nosso servidor back-end, ele será executado em uma porta número 3000 diferente. Isso será o caso até que estejamos prontos para produção.

Não há nada que nos impeça de executá-los na mesma porta. Na verdade, acabará sendo o caso no final. Se nos lembrarmos, estamos indo para o mesmo domínio abordagem. Vamos executar o back-end e o front-end em portas diferentes por enquanto. Isso ocorre porque queremos tirar proveito dos muitos recursos úteis do Vue.js servidor de desenvolvimento. Abordaremos como mesclar os dois (frente e back-end) em um capítulo posterior.

Antes de prosseguir, vamos destacar um problema aqui. Existe uma desvantagem em desenvolver nosso aplicativo em portas diferentes. É chamado Compartilhamento de solicitação de origem cruzada , abreviadamente denominado CORS. Por padrão, não nos permitirá fazer domínio cruzado Solicitações Ajax para nosso back-end. Existe um Node.js biblioteca para encontrar uma maneira de contornar isso, mas vamos deixar isso para outro tutorial.

o Vue.js servidor de desenvolvimento tem algo chamado proxy . Ele permite que nosso servidor back-end pense que o front-end está sendo executado na mesma porta que ele. Para habilitar esse recurso, abra o arquivo de configuração em config/index.js. Sob o dev propriedade, adicione um objeto como:

proxyTable: { '/api': 'http://localhost:3000' },

No código acima, estamos redirecionando as solicitações Ajax que começam com /incêndio para o URL [http://localhost:3000](http://localhost:3000 'http://localhost:3000'). Observe que isso é diferente do URL em que nosso aplicativo front-end está sendo executado. Se não tivermos esse código, as solicitações Ajax por padrão são enviadas para [http://localhost:8080](http://localhost:8080 'http://localhost:8080'), que não é o que queremos. Quando estiver pronto para a produção, podemos removê-lo:

Por fim, instale a biblioteca de cookies front-end usando:

npm install vue-cookies --save

Protegendo nossa API de back-end

Vamos agora configurar um Node.js Processo interno. Em primeiro lugar, precisamos ter Node.js instalado em seu sistema para esta parte também. Vá até uma janela de terminal. Crie uma pasta vazia chamada vueauthclient-backend. Navegue até a pasta usando:

cd vueauthclient-backend

Em seguida, inicialize um novo Node.js aplicativo usando o comando:

npm init

Haverá vários prompts. Vamos aceitar os padrões e especificar os valores quando necessário. Devemos terminar com um arquivo chamado package.json. Crie um arquivo chamado index.js no diretório raiz do projeto. É aqui que nosso código principal ficará. Instale várias bibliotecas usando o comando:

atualizar a versão do nó ubuntu
npm install --save body-parser cookie-session express passport passport-local

No topo do index.js arquivo, importe as bibliotecas usando o código:

const express = require('express') // creating an express instance const app = express() const cookieSession = require('cookie-session') const bodyParser = require('body-parser') const passport = require('passport') // getting the local authentication type const LocalStrategy = require('passport-local').Strategy

Primeiro, vamos inicializar o sessão de cookie e a analisador de corpo bibliotecas usando:

app.use(bodyParser.json()) app.use(cookieSession({ name: 'mysession', keys: ['vueauthrandomkey'], maxAge: 24 * 60 * 60 * 1000 // 24 hours }))

Estamos configurando o cookie para expirar após 24 horas. A seguir, vamos instruir nosso Node.js aplicativo que queremos usar Passport.js . Faça isso adicionando a linha:

app.use(passport.initialize());

Em seguida, diga Passport.js para iniciar seu sistema de gerenciamento de sessão:

app.use(passport.session());

Uma vez que não usaremos um banco de dados real para gerenciar usuários, para fins de brevidade, usaremos um array para isso. Adicione as seguintes linhas:

let users = [ { id: 1, name: 'Jude', email: 'user@email.com', password: 'password' }, { id: 2, name: 'Emma', email: 'emma@email.com', password: 'password2' } ]

A seguir, vamos configurar os URLs para fazer login, fazer logout e obter dados do usuário. Eles serão encontrados em POST /api/login, GET /api/logout e GET /api/user, respectivamente. Para a parte de login, cole o seguinte:

app.post('/api/login', (req, res, next) => { passport.authenticate('local', (err, user, info) => { if (err) { return next(err); } if (!user) { return res.status(400).send([user, 'Cannot log in', info]); } req.login(user, err => { res.send('Logged in'); }); })(req, res, next); });

Aqui, estamos instruindo Express.js para autenticar o usuário usando as credenciais fornecidas. Se ocorrer um erro ou se ele falhar, retornamos uma mensagem de erro ao front-end. Se o usuário estiver logado, responderemos com uma mensagem de sucesso. Passport.js lida com a verificação de credenciais. Faremos isso em breve. Observe que o método passport.authenticate reside no Passport.js biblioteca.

O próximo URL que iremos configurar é logout. Isso invalida nosso biscoito se houver. Adicione isso para obter a funcionalidade:

app.get('/api/logout', function(req, res) { req.logout(); console.log('logged out') return res.send(); });

Finalmente, o URL para obter os dados dos usuários conectados no momento. Quando conectado, Passport.js adiciona um objeto de usuário à solicitação usando o cookie do front-end como um identificador. Temos que usar o id desse objeto para obter os dados do usuário necessários de nosso array de dados no back-end. Cole o seguinte:

app.get('/api/user', authMiddleware, (req, res) => { let user = users.find(user => { return user.id === req.session.passport.user }) console.log([user, req.session]) res.send({ user: user }) })

Observe que, desta vez, temos uma segunda variável que passamos antes do retorno de chamada. Isso ocorre porque queremos proteger esta URL, então estamos passando um filtro de middleware. Este filtro irá verificar se a sessão atual é válida antes de permitir que o usuário prossiga com o resto da operação. Vamos criar o middleware usando:

const authMiddleware = (req, res, next) => { if (!req.isAuthenticated()) { res.status(401).send('You are not authenticated') } else { return next() } }

Temos que nos certificar de declará-lo antes de criar a rota de API para /api/user.

A seguir, vamos configurar Passport.js então ele sabe como nos conectar. Após o login, ele armazenará os dados do objeto do usuário em um sessão de cookie e recupere os dados em solicitações posteriores. Para configurar Passport.js usando o estratégia local , adicione o seguinte:

passport.use( new LocalStrategy( { usernameField: 'email', passwordField: 'password' }, (username, password, done) => { let user = users.find((user) => { return user.email === username && user.password === password }) if (user) { done(null, user) } else { done(null, false, { message: 'Incorrect username or password'}) } } ) )

Aqui, estamos instruindo Passport.js para usar o LocalStrategy nós criamos acima. Também estamos especificando quais campos esperar do front-end, pois ele precisa de um nome de usuário e senha. Então, estamos usando esses valores para consultar o usuário. Se forem válidos, chamamos o done retorno de chamada, que armazenará o objeto de usuário na sessão. Se não for válido, chamaremos o retorno de chamada concluído com um false valor e retornar com um erro. Uma coisa a ser observada é que o código acima funciona em conjunto com o login URL A chamada para passport.authenticate nesse URL o retorno de chamada aciona o código acima.

Em seguida, vamos contar Passport.js como lidar com um determinado objeto de usuário. Isso é necessário se quisermos fazer algum trabalho antes de armazená-lo na sessão. Neste caso, queremos apenas armazenar o id, pois é suficiente para identificar o usuário ao extraí-lo do cookie. Adicione o seguinte para conseguir isso:

passport.serializeUser((user, done) => { done(null, user.id) })

A seguir, vamos configurar o inverso. Quando um usuário faz uma solicitação de URL seguro. Dizemos ao passaporte como recuperar o objeto de usuário de nossa matriz de usuários. Ele usará o id que armazenamos usando serializeUser método para conseguir isso. Adicione isso:

passport.deserializeUser((id, done) => { let user = users.find((user) => { return user.id === id }) done(null, user) })

Agora, vamos adicionar o código que inicializa o Node.js servidor usando o seguinte:

app.listen(3000, () => { console.log('Example app listening on port 3000') })

Execute o comando:

node index.js

Isso realmente inicia o servidor. Haverá uma mensagem no console com o texto Exemplo de aplicativo ouvindo na porta 3000 .

Preparando-se para a produção

Agora, quando visitarmos a página localhost:8080, devemos ver um formulário de login. Quando enviamos o formulário, somos redirecionados para a página do painel. Conseguimos isso usando o proxy que configuramos anteriormente.

vue-loading-overlay

Isso é aceitável para o desenvolvimento - mas vai contra o propósito de ter um mesmo domínio aplicativo. Ter um mesmo domínio cenário, precisamos compilar nosso aplicativo para produção.

Antes disso, vamos testar se o proxy está funcionando. Comente o código do URL do proxy em config/index.js. Podemos precisar reiniciar o servidor de desenvolvimento porque alteramos um arquivo de configuração.

Agora, vamos revisitar a página de login e enviar o formulário. Obteremos um erro dizendo que não temos permissão para acessar o servidor back-end. Para contornar isso, precisamos configurar nosso Node.js servidor back-end. O back-end agora servirá nosso aplicativo front-end em vez do servidor de desenvolvimento.

No console do front-end, execute o comando:

npm run build

Isso irá gerar todos os arquivos necessários para a produção. Podemos encontrar todos os arquivos criados a partir deste comando em dist pasta. Deste ponto em diante, temos duas opções: podemos copiar esta pasta para que faça parte do nosso Node.js aplicativo ou podemos dizer o Node.js servidor para se referir diretamente a ele em nosso sistema de arquivos. O último é útil se ainda os quisermos como repositórios separados. Usaremos o último método.

Navegue até a pasta dist. Execute o comando pwd para obter o caminho absoluto da pasta dist, supondo que estejamos em um sistema baseado em Linux ou Mac. Se estivermos no Windows, podemos obter o caminho absoluto para a pasta usando um comando equivalente.

Copie o caminho absoluto, mas não se esqueça de reiniciar o Node.js servidor após qualquer modificação. Já que não queremos reiniciar o servidor, vamos instalar Nodemon . Ele pode cuidar disso para nós quando nosso código mudar.

Em seguida, cole o seguinte após as instruções de importação:

const publicRoot = '/absolute/path/to/dist' app.use(express.static(publicRoot))

Isso informa ao servidor onde procurar os arquivos.

A etapa final será adicionar uma rota à raiz de nosso Node.js aplicativo. É assim que serve ao pronto para produção código que compilamos. Faça isso adicionando:

app.get('/', (req, res, next) => { res.sendFile('index.html', { root: publicRoot }) })

Agora, mesmo com o proxy desabilitado, vamos visitar a raiz do servidor localhost:3000. Veremos o formulário de login. Envie isso e devemos ver a página do painel com o nome de usuário exibido.

Funcionalidade de logout e dados de login

Observe que nosso aplicativo ainda está usando dados codificados permanentemente, queremos obtê-los no formulário enviado. Altere essas linhas no componente de login de:

let email = 'user@email.com' let password = 'password'

para:

let email = e.target.elements.email.value let password = e.target.elements.password.value

Agora, estamos usando os dados do formulário. A seguir, vamos configurar um link para nos desconectar. No componente src/App.vue, altere o modelo para este:

  postagem do blog aqui . Isso ajudará na criação e construção de um básico Vue.js aplicativo.

Além disso, não se esqueça de proteger seu aplicativo Vue.js contra roubo de código e engenharia reversa. Ver nosso guia prático sobre a proteção de aplicativos Vue.js com Jscrambler.

Publicado originalmente por Jscrambler em blog.jscrambler

# node-js # vue-js