Segurança
Segurança
Segurança
Segurança
Mais preocupações
Restrição pela infraestrutura
Comunicação HTTP
Certificado SSL
mkdir certs
cd certs
mkcert -install
mkcert localhost
Gerando um certificado SSL
//...
const fs = require('fs');
const https = require('https');
//...
const portaHttp = 443;
//...
const key = fs.readFileSync('config/localhost-key.pem', 'utf8');
const cert = fs.readFileSync('config/localhost.pem', 'utf8');
const credentials = { key, cert };
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(portaHttp, () => {
console.log(`API rodando na porta ${portaHttp}`);
});
Adicionando a API
CORS
CORS
//...
const cors = require('cors');
// Configure para aceitar requisições de qualquer origem
app.use(cors());
// ou
// Especifique uma origem para limitar o acesso aos recursos
app.use(cors({origin: ["https://*.example.com"] }));
Adicionando o CORS a API
yarn add cors
Autenticação
Autorização
Authorization
Token-based Authorization
Token-based Authorization
JWT
yarn add jsonwebtoken
// ou
npm install jsonwebtoken
Gerando um token JWT
{
"secret": "palavraSecreta"
}
config/security.json
const jwt = require('jsonwebtoken');
const { Usuario } = require('../models');
const { secret } = require('../config/security.json');
const controller = {};
controller.login = async (email, senha) => {
try {
const usuario = await Usuario.findOne({ where: { email } });
if (usuario.senha != senha) return false;
return jwt.sign({ id: usuario.id }, secret, {
expiresIn: '24h',
});
} catch (error) {
console.log(error);
throw new Error(error);
}
};
module.exports = controller;
controller/usuario.js
const { Router } = require('express');
const router = Router();
const { login } = require('../controller/usuario');
router.post('/', async (req, res) => {
try {
const { email, senha } = req.body;
const token = await login(email, senha);
if (token) {
res.send({ token });
} else {
res.status(401).send({ error: 'Login ou senha inválidos' });
}
} catch (error) {
res.status(500).send({ error });
}
});
module.exports = router;
login.js
// ...
app.use('/login', login);
app.use('/usuario', usuario);
// ...
app.js
Utilizando Middlewares
const jwt = require('jsonwebtoken');
const { secret } = require('../config/security');
module.exports = (req, res, next) => {
const token = req.headers['Authorization'];
if (!token) return res.status(401).send({ error: 'Token não informado' });
jwt.verify(token, secret, (error, decoded) => {
if (error) return res.status(500).send(error);
const { id } = jwt.decode(token);
req.usuarioId = id;
next();
});
};
middlewares/auth.js
// ...
app.use('/login', login);
app.use(auth);
app.use('/usuario', usuario);
// ...
app.js
Exposição de dados
Acesso a dados sensíveis
Pacote BCrypt
Salt
yarn add bcrypt
// ou
npm install bcrypt
Pacote BCrypt
{
"secret": "palavraSecreta",
"saltos": 10
}
config/token.json
const bcrypt = require('bcrypt');
const { saltos } = require('../config/token');
module.exports = function (sequelize, DataTypes) {
return sequelize.define(
'usuario',
{
// atributos
},
{
//...
hooks: {
beforeValidate: (usuario) => {
if (usuario.senha) usuario.senha = bcrypt.hashSync(usuario.senha, saltos);
},
},
}
);
};
bd/usuario.js
const bcrypt = require('bcrypt');
const { Usuario } = require('../bd');
const jwt = require('jsonwebtoken');
const { secret } = require('../config/token.json');
const controller = {};
controller.login = async (email, senha) => {
try {
const usuario = await Usuario.findOne({ where: { email } });
const senhaCorreta = await bcrypt.compare(senha, usuario.senha);
if (!senhaCorreta) return false;
return jwt.sign({ id: usuario.id }, secret, {
expiresIn: '24h',
});
} catch (error) {
console.log(error);
throw new Error(error);
}
};
module.exports = controller;
controle/usuario.js
module.exports = function (sequelize, DataTypes) {
return sequelize.define(
'usuario',
{
// atributos
},
{
//...
defaultScope: {
attributes: {
exclude: ['senha'],
},
},
scopes: {
login: {
attributes: ['id', 'senha'],
},
}
}
);
};
bd/usuario.js
const bcrypt = require('bcrypt');
const { Usuario } = require('../bd');
const jwt = require('jsonwebtoken');
const { secret } = require('../config/token.json');
const controller = {};
controller.login = async (email, senha) => {
try {
const usuario = await Usuario.scope('login').findOne({ where: { email } });
const senhaCorreta = await bcrypt.compare(senha, usuario.senha);
if (!senhaCorreta) return false;
return jwt.sign({ id: usuario.id }, secret, {
expiresIn: '24h',
});
} catch (error) {
console.log(error);
throw new Error(error);
}
};
module.exports = controller;
controle/usuario.js
Limitando acesso por usuário
const { Router } = require("express");
const { Nota, Checklist, sequelize } = require("../bd");
const router = Router();
router.post("/", async (req, res) => {
//...
const { body, usuarioId } = req;
body = { ...body, usuarioId };
checklists = body.checklists;
//..
res.send(nota);
});
rotas/usuario.js
const { Router } = require("express");
const { Nota, Checklist, sequelize } = require("../bd");
const router = Router();
router.get("/:id?", async (req, res) => {
//...
const { usuarioId } = req;
if (req.params.id) {
resultado = await Usuario.findOne({
where: {
id: req.params.id,
usuarioId
}
});
} else {
result = await Usuario.findAll({
where: {
usuarioId,
},
});
}
//..
res.send(result);
});
rotas/usuario.js