Enviando dados de um lugar para outro? Para sua própria tranquilidade e proteção de seus usuários, você deve protegê-lo com o JWT.
Ao criar um aplicativo, é vital proteger dados confidenciais contra acesso não autorizado. Muitos aplicativos modernos da web, móveis e em nuvem usam APIs REST como o principal meio de comunicação. Como resultado, é crucial projetar e desenvolver APIs de back-end com segurança em primeiro lugar.
Uma abordagem eficaz para proteger uma API REST envolve JSON Web Tokens (JWTs). Esses tokens oferecem um mecanismo robusto para autenticação e autorização do usuário, ajudando a proteger os recursos protegidos contra o acesso de agentes mal-intencionados.
O que são tokens da Web JSON?
Token da Web JSON (JWT) é um padrão de segurança amplamente utilizado. Ele fornece um método conciso e independente de transmissão segura de dados entre um aplicativo cliente e um sistema de back-end.
Uma API REST pode usar JWTs para identificar e autenticar usuários com segurança quando eles fazem solicitações HTTP para acessar recursos protegidos.
Um JSON Web Token consiste em três partes distintas: o cabeçalho, a carga útil e a assinatura. Ele codifica cada parte e as concatena usando um ponto (".").
O cabeçalho descreve o algoritmo criptográfico usado para assinar o token, enquanto a carga útil contém dados sobre o usuário e quaisquer metadados adicionais.
Por fim, a assinatura, calculada usando o cabeçalho, a carga útil e a chave secreta, garante a integridade e a autenticidade do token.
Com o básico dos JWTs resolvidos, vamos criar uma API REST Node.js e implementar JWTs.
Configurar um aplicativo Express.js e um banco de dados MongoDB
Você descobrirá aqui como criar uma autenticação simples API REST que lida com a funcionalidade de registro e login. Depois que o processo de login autenticar um usuário, ele poderá fazer solicitações HTTP para uma rota de API protegida.
Você pode encontrar o código do projeto neste Repositório GitHub.
Para começar, criar um servidor web Expresse instale estes pacotes:
npm install cors dotenv bycrpt mongoose cookie-parser crypto jsonwebtoken mongodb
Próximo, criar um banco de dados MongoDB ou configurar um cluster MongoDB na nuvem. Em seguida, copie a string de conexão do banco de dados, crie um .env arquivo no diretório raiz e cole na string de conexão:
CONNECTION_STRING="string de conexão"
Configurar a conexão do banco de dados
Crie um novo utils/db.js arquivo no diretório raiz da pasta do seu projeto. Nesse arquivo, adicione o seguinte código para estabelecer a conexão com o banco de dados usando o Mongoose.
const mangusto = exigir('mangusto');
const conectarDB = assíncrono () => {
tentar {
aguardam mongoose.connect (process.env. CONNECTION_STRING);
console.registro("Conectado ao MongoDB!");
} pegar (erro) {
console.erro("Erro ao conectar-se ao MongoDB:", erro);
}
};
módulo.exports = connectDB;
Definir o modelo de dados
Defina um esquema simples de dados do usuário usando o Mongoose. No diretório raiz, crie um novo modelo/usuário.model.js arquivo e adicione o seguinte código.
const mangusto = exigir('mangusto');
const userSchema = novo mangusto. Esquema({
nome de usuário: Corda,
senha: {
tipo: Corda,
obrigatório: verdadeiro,
exclusivo: verdadeiro,
},
});
const Usuário = mangusto.model("Do utilizador", userSchema);
módulo.exports = Usuário;
Defina os controladores para as rotas de API
As funções do controlador gerenciarão o registro e o login; eles são uma parte substancial deste programa de amostra. No diretório raiz, crie um controllers/userControllers.js arquivo e adicione o seguinte código:
- Defina o controlador de registro do usuário.
Este trecho de código faz o hash da senha fornecida usando bcrypt e, em seguida, cria um novo registro de usuário no banco de dados, armazenando o nome de usuário e a senha com hash. Se o registro for bem-sucedido, ele enviará uma resposta com uma mensagem de sucesso.const Usuário = exigir('../models/user.model');
const bcrypt = exigir('bcrypt');
const { gerarToken } = exigir('../middleware/auth');exports.registerUser = assíncrono (req, res) => {
const { nome de usuário, senha } = req.body;tentar {
const hash = aguardam bcrypt.hash (senha, 10);
aguardam User.create({ nome de usuário, senha: cerquilha });
res.status(201).enviar({ mensagem: 'Usuário cadastrado com sucesso' });
} pegar (erro) {
console.log (erro);
res.status(500).enviar({ mensagem: 'Um erro ocorreu!! ' });
}
}; - Defina um controlador de login para gerenciar o processo de login do usuário:
Quando um usuário envia uma solicitação ao /login rota, eles devem passar suas credenciais de autenticação no corpo da solicitação. O código então verifica essas credenciais e gera um JSON Web Token. O token é armazenado com segurança em um cookie com o httpOnly sinalizador definido como verdadeiro. Isso impede que o JavaScript do lado do cliente acesse o token, protegendo contra possíveis ataques de script entre sites (XSS).exports.loginUser = assíncrono (req, res) => {
const { nome de usuário, senha } = req.body;tentar {
const usuário = aguardam User.findOne({ nome de usuário });
se (!do utilizador) {
retornar res.status(404).enviar({ mensagem: 'Usuário não encontrado' });
}const passwordMatch = aguardam bcrypt.compare (senha, usuário.senha);
se (!passwordMatch) {
retornar res.status(401).enviar({ mensagem: 'Credenciais de login inválidas' });
}const carga útil = { ID do usuário: ID do usuário };
const token = gerarToken (carga útil);
res.cookie('símbolo', símbolo, { httpOnly: verdadeiro });
res.status(200).json({ mensagem: 'Login com sucesso'});
} pegar (erro) {
console.log (erro);
res.status(500).enviar({ mensagem: 'Ocorreu um erro ao fazer login' });
}
}; - Finalmente, defina uma rota protegida:
Ao armazenar o JWT em um cookie, as solicitações de API subsequentes do usuário autenticado incluirão automaticamente o token, permitindo que o servidor valide e autorize as solicitações.exports.getUsers = assíncrono (req, res) => {
tentar {
const usuários = aguardam User.find({});
res.json (usuários);
} pegar (erro) {
console.log (erro);
res.status(500).enviar({ mensagem: 'Um erro ocorreu!!' });
}
};
Criar um middleware de autenticação
Agora que você definiu um controlador de login que gera um token JWT após uma autenticação bem-sucedida, defina as funções de autenticação de middleware que irão gerar e verificar o token JWT.
No diretório raiz, crie uma nova pasta, middleware. Dentro desta pasta, adicione dois arquivos: auth.js e config.js.
Adicione este código a config.js:
const cripto = exigir('cripto');
módulo.exportações = {
secretKey: crypto.randomBytes(32).para sequenciar('hex')
};
Esse código gera uma nova chave secreta aleatória toda vez que é executado. Você pode usar essa chave secreta para assinar e verificar a autenticidade dos JWTs. Depois que um usuário for autenticado com sucesso, gere e assine um JWT com a chave secreta. O servidor usará a chave para verificar se o JWT é válido.
Adicione o seguinte código em auth.js que define funções de middleware que geram e verificam os JWTs.
const jwt = exigir('jsonwebtoken');
const { chave secreta } = exigir('./config');const gerarToken = (carga útil) => {
const token = jwt.sign (payload, secretKey, { expira em: '1h' });
retornar símbolo ;
};const verificarToken = (req, res, próximo) => {
const token = req.cookies.token;se (!símbolo) {
retornar res.status(401).json({ mensagem: 'Nenhum token fornecido' });
}jwt.verify (token, secretKey, (err, decodificado) => {
se (err) {
retornar res.status(401).json({ mensagem: 'Token inválido' });
}req.userId = decodificado.userId;
próximo();
});
};
módulo.exports = { gerarToken, verificarToken };
O gerarToken A função gera um JWT assinando uma carga útil usando uma chave secreta e definindo um tempo de expiração enquanto o VerifyToken A função serve como middleware para verificar a autenticidade e a validade de um token fornecido.
Definir as rotas da API
Crie um novo rotas/userRoutes.js arquivo no diretório raiz e adicione o seguinte código.
const expresso = exigir('expressar');
const roteador = expresso. Roteador();
const userControllers = exigir('../controllers/userControllers');
const {verificarToken} = exigir('../middleware/auth');
roteador.post('/api/registro', userControllers.registerUser);
roteador.post('/api/login', userControllers.loginUser);
router.get('/api/usuários',verifyToken, userControllers.getUsers);
módulo.exports = roteador;
Atualize seu ponto de entrada do servidor
Atualize seu server.js arquivo com o seguinte código.
const expresso = exigir('expressar');
const cors = exigir('cors');
const aplicativo = expresso();
const porta = 5000;
exigir('dotenv').config();
const conectarDB = exigir('./utils/db');
const cookieParser = exigir('analisador de cookies');conectarDB();
app.use (express.json());
app.use (express.urlencoded({ estendido: verdadeiro }));
app.use (cors());
app.use (cookieParser());
const userRoutes = exigir('./routes/userRoutes');
app.use('/', userRoutes);
app.listen (porta, () => {
console.registro(`Servidor está escutando em http://localhost:${porta}`);
});
Para testar a API REST, ative o servidor de desenvolvimento e faça solicitações de API para os endpoints definidos:
node server.js
Protegendo as APIs REST do Node.js
Proteger APIs REST Node.js vai além de apenas usar JWTs, embora eles desempenhem um papel crucial na autenticação e autorização, é essencial adotar uma abordagem de segurança holística para proteger seu back-end sistemas. Juntamente com os JWTs, você também deve considerar a implementação de HTTPS para criptografar a comunicação, validação e sanitização de entrada e muitos outros.
Ao combinar várias medidas de segurança, você pode estabelecer uma estrutura de segurança robusta para o seu APIs REST Node.js e minimizam o risco de acesso não autorizado, violações de dados e outros problemas de segurança ameaças.