Descubra como combinar essas tecnologias com uma demonstração prática.

O controle de acesso baseado em função é um mecanismo de autenticação seguro. Você pode usá-lo para restringir o acesso a recursos específicos para usuários com determinadas funções.

Esse tipo de autenticação ajuda os administradores do sistema a controlar as permissões de acordo com as funções designadas dos usuários. Esse nível de controle granular adiciona uma camada de segurança, permitindo que os aplicativos impeçam o acesso não autorizado.

Implementando o mecanismo de controle de acesso baseado em função usando Passport.js e JWTs

O controle de acesso baseado em função (RBAC) é um mecanismo popular usado para impor restrições de acesso em aplicativos com base em funções e permissões do usuário. Existem vários métodos disponíveis para implementar o mecanismo RBAC.

Duas abordagens populares incluem o uso de bibliotecas RBAC dedicadas como Controle de acesso ou aproveitando as bibliotecas de autenticação existentes para implementar o mecanismo.

instagram viewer

Nesse caso, JSON Web Tokens (JWTs) fornecem uma maneira segura de transmitir credenciais de autenticação, enquanto o Passport.js simplifica o processo de autenticação fornecendo autenticação flexível middleware.

Usando essa abordagem, você pode atribuir funções aos usuários e codificá-los no JWT quando eles forem autenticados. Você pode então usar o JWT para verificar a identidade e as funções do usuário em solicitações subsequentes, permitindo autorização baseada em função e controle de acesso.

Ambas as abordagens têm suas vantagens e podem ser eficazes na implementação do RBAC. A escolha entre qual método implementar dependerá dos requisitos específicos do seu projeto.

Você pode baixar o código deste projeto em seu Repositório GitHub.

Configurar um projeto Express.js

Para começar, configurar um projeto Express.js localmente. Depois de configurar o projeto, vá em frente e instale estes pacotes:

npm install cors dotenv mongoose cookie-parser jsonwebtoken mongodb \
passaporte passaporte-local

Próximo, criar um banco de dados MongoDB ou configurar um cluster no MongoDB Atlas. Copie o URI de conexão do banco de dados e adicione-o a um .env arquivo no diretório raiz do seu projeto do seu projeto:

CONNECTION_URI="URI de conexão"

Configurar a conexão do banco de dados

No diretório raiz, crie um novo utils/db.js arquivo e adicione o código abaixo para estabelecer a conexão com o cluster MongoDB em execução no Atlas usando o Mongoose.

const mangusto = exigir('mangusto');

const conectarDB = assíncrono () => {
tentar {
aguardam mongoose.connect (process.env. CONNECTION_URI);
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

No diretório raiz, crie um novo modelo/usuário.model.js arquivo e adicione o código a seguir para definir um modelo de dados para os dados dos usuários usando o Mongoose.

const mangusto = exigir('mangusto');

const userSchema = novo mangusto. Esquema({
nome de usuário: Corda,
senha: Corda,
papel: Corda
});

módulo.exports = mangusto.model('Do utilizador', userSchema);

Crie o controlador para os endpoints da API

Crie um novo controladores/usuário.controlador.js arquivo no diretório raiz e adicione o código abaixo.

Primeiro, faça estas importações:

const Usuário = exigir('../models/user.model');
const passaporte = exigir('Passaporte');
const { gerarToken } = exigir('../middleware/auth');
exigir('../middleware/passaporte')(Passaporte);

Em seguida, defina a lógica para gerenciar o registro do usuário e a funcionalidade de login:

exports.registerUser = assíncrono (req, res) => {
const { nome de usuário, senha, função } = req.body;

tentar {
aguardam User.create({ nome de usuário, senha, função });
res.status(201).json({ mensagem: 'Usuário cadastrado com sucesso' });
} pegar (erro) {
console.log (erro);
res.status(500).json({ mensagem: 'Um erro ocorreu!' });
}
};

exports.loginUser = (req, res, próximo) => {
passaporte.autenticar('local', { sessão: falso }, (err, usuário, info) => {
se (err) {
console.log (erro);

retornar res.status(500).json({
mensagem: 'Ocorreu um erro ao fazer login'
});
}

se (!do utilizador) {
retornar res.status(401).json({
mensagem: 'Credenciais de login inválidas'
});
}

req.login (usuário, { sessão: falso }, (erro) => {
se (err) {
console.log (erro);

retornar res.status(500).json({
mensagem: 'Ocorreu um erro ao fazer login'
});
}

const { _id, nome de usuário, função } = usuário;
const carga útil = { ID do usuário: _id, nome de usuário, função };
const token = gerarToken (carga útil);
res.cookie('símbolo', símbolo, { httpOnly: verdadeiro });
retornar res.status(200).json({ mensagem: 'Login com sucesso' });
});
})(req, res, próximo);
};

O registrarUsuário A função lida com o registro de um novo usuário extraindo o nome de usuário, a senha e a função do corpo da solicitação. Em seguida, ele cria uma nova entrada de usuário no banco de dados e responde com uma mensagem de sucesso ou um erro, se ocorrer durante o processo.

Por outro lado, o loginUser A função facilita o login do usuário utilizando a estratégia de autenticação local fornecida pelo Passport.js. Ele autentica as credenciais do usuário e retorna um token após o login bem-sucedido, que é armazenado em um cookie para solicitações subsequentes autenticadas. Se algum erro ocorrer durante o processo de login, ele retornará uma mensagem apropriada.

Finalmente, adicione o código que implementa a lógica que busca todos os dados dos usuários do banco de dados. Usaremos esse ponto de extremidade como a rota restrita para garantir que apenas usuários autorizados com a função de administrador pode acessar este terminal.

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).json({ mensagem: 'Um erro ocorreu!' });
}
};

Configurar uma estratégia de autenticação local do Passport.js

Para autenticar os usuários após eles fornecerem suas credenciais de login, você precisa configurar uma estratégia de autenticação local.

Crie um novo middleware/passport.js arquivo no diretório raiz e adicione o seguinte código.

const LocalStrategy = exigir('passaporte-local').Estratégia;
const Usuário = exigir('../models/user.model');

módulo.exportações = (Passaporte) => {
passaporte.uso(
novo LocalStrategy(assíncrono (nome de usuário, senha, pronto) => {
tentar {
const usuário = aguardam User.findOne({ nome de usuário });

se (!do utilizador) {
retornar feito(nulo, falso);
}

se (usuário.senha !== senha) {
retornar feito(nulo, falso);
}

retornar feito(nulo, do utilizador);
} pegar (erro) {
retornar feito (erro);
}
})
);
};

Esse código define uma estratégia local do passaporte.js para autenticar usuários com base no nome de usuário e na senha fornecidos.

Primeiro, ele consulta o banco de dados para encontrar um usuário com um nome de usuário correspondente e, em seguida, valida sua senha. Consequentemente, ele retorna o objeto de usuário autenticado se o processo de login for bem-sucedido.

Criar um middleware de verificação JWT

Dentro de middleware diretório, crie um novo arquivo auth.js e inclua o código a seguir para definir um middleware que gera e verifica JWTs.

const jwt = exigir('jsonwebtoken');
const secretKey = process.env. CHAVE SECRETA;

const gerarToken = (carga útil) => {
const token = jwt.sign (payload, secretKey, { expira em: '1h' });
retornar símbolo;
};

const verificarToken = (obrigatórioPapel) =>(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;

se (decoded.role !== requiredRole) {
retornar res.status(403).json({
mensagem: 'Você não tem autorização e permissões para acessar este recurso.'
});
}

próximo();
});
};

módulo.exports = { gerarToken, verificarToken };

O gerarToken função cria um JWT com um tempo de expiração especificado, enquanto o VerifyToken A função verifica se o token está presente e é válido. Além disso, também verifica se o token decodificado contém a função necessária, essencialmente, garantindo que apenas usuários com a função e permissões autorizadas tenham acesso.

Para assinar exclusivamente os JWTs, você precisa gerar uma chave secreta exclusiva e adicioná-la ao seu .env arquivo como mostrado abaixo.

SECRET_KEY="Esta é uma amostra de chave secreta."

Definir as rotas da API

No diretório raiz, crie uma nova pasta e nomeie-a como routes. Dentro desta pasta, crie um novo userRoutes.jse adicione o código a seguir.

const expresso = exigir('expressar');
const roteador = expresso. Roteador();
const userControllers = exigir('../controllers/userController');
const {verificarToken} = exigir('../middleware/auth');

roteador.post('/api/registro', userControllers.registerUser);
roteador.post('/api/login', userControllers.loginUser);

router.get('/api/usuários', verifiqueToken('administrador'), userControllers.getUsers);

módulo.exports = roteador;

Este código define as rotas HTTP para uma API REST. O Usuários rota especificamente, servidores como a rota protegida. Ao limitar o acesso aos usuários com o administrador função, você reforça efetivamente o controle de acesso baseado em função.

Atualize o arquivo do servidor principal

Abre o teu server.js arquivo e atualize-o da seguinte forma:

const expresso = exigir('expressar');
const cors = exigir('cors');
const cookieParser = exigir('analisador de cookies');
const aplicativo = expresso();
const porta = 5000;
exigir('dotenv').config();
const conectarDB = exigir('./utils/db');
const passaporte = exigir('Passaporte');
exigir('./middleware/passaporte')(Passaporte);

conectarDB();

app.use (express.json());
app.use (express.urlencoded({ estendido: verdadeiro }));
app.use (cors());
app.use (cookieParser());
app.use (passport.initialize());

const userRoutes = exigir('./routes/userRoutes');
app.use('/', userRoutes);

app.listen (porta, () => {
console.registro(`Servidor está rodando na porta ${porta}`);
});

Por fim, inicie o servidor de desenvolvimento para executar o aplicativo.

node server.js

Aproveite o mecanismo RBAC para elevar seus sistemas de autenticação

A implementação do controle de acesso baseado em função é uma maneira eficaz de aumentar a segurança de seus aplicativos.

Embora a incorporação de bibliotecas de autenticação existentes para estabelecer um sistema RBAC eficiente seja uma ótima abordagem, aproveitar as bibliotecas RBAC para definir explicitamente as funções do usuário e atribuir permissões fornece uma solução ainda mais robusta, em última análise, aprimorando a segurança geral do seu aplicativo.