Scopri come combinare queste tecnologie con una dimostrazione pratica.

Il controllo degli accessi in base al ruolo è un meccanismo di autenticazione sicuro. Puoi usarlo per limitare l'accesso a risorse specifiche agli utenti che hanno determinati ruoli.

Questo tipo di autenticazione aiuta gli amministratori di sistema a controllare le autorizzazioni in base ai ruoli designati dagli utenti. Questo livello di controllo granulare aggiunge un livello di sicurezza, consentendo alle app di impedire l'accesso non autorizzato.

Implementazione del meccanismo di controllo degli accessi basato sui ruoli utilizzando Passport.js e JWT

Il controllo degli accessi in base al ruolo (RBAC) è un meccanismo diffuso utilizzato per imporre restrizioni di accesso nelle applicazioni in base ai ruoli e alle autorizzazioni dell'utente. Sono disponibili vari metodi per implementare il meccanismo RBAC.

Due approcci popolari includono l'utilizzo di librerie RBAC dedicate come AccessControl o sfruttando le librerie di autenticazione esistenti per implementare il meccanismo.

instagram viewer

In questo caso, i token Web JSON (JWT) forniscono un modo sicuro per trasmettere le credenziali di autenticazione, mentre Passport.js semplifica il processo di autenticazione fornendo un'autenticazione flessibile middleware.

Utilizzando questo approccio, puoi assegnare ruoli agli utenti e codificarli nel JWT quando si autenticano. È quindi possibile utilizzare JWT per verificare l'identità e i ruoli dell'utente nelle richieste successive, consentendo l'autorizzazione basata sui ruoli e il controllo degli accessi.

Entrambi gli approcci hanno i loro vantaggi e possono essere efficaci nell'implementazione del controllo degli accessi in base al ruolo. La scelta tra quale metodo implementare dipenderà dai requisiti specifici del progetto.

Puoi scaricare il codice di questo progetto dal suo file Deposito GitHub.

Configurare un progetto Express.js

Per iniziare, configurare un progetto Express.js in locale. Una volta impostato il progetto, vai avanti e installa questi pacchetti:

npm install cors dotenv mongoose cookie-parser jsonwebtoken mongodb \
passaporto passaporto locale

Prossimo, creare un database MongoDB O impostare un cluster su MongoDB Atlas. Copia l'URI di connessione al database e aggiungilo a a .env file nella directory principale del tuo progetto:

CONNECTION_URI="URI di connessione"

Configurare la connessione al database

Nella directory principale, crea un nuovo file utils/db.js file e aggiungi il codice seguente per stabilire la connessione al cluster MongoDB in esecuzione su Atlas utilizzando Mongoose.

cost mangusta = richiedere('mangusta');

cost connectDB = asincrono () => {
Tentativo {
aspetta mongoose.connect (processo.env. URI_CONNESSIONE);
consolare.tronco d'albero("Connesso a MongoDB!");
} presa (errore) {
consolare.errore("Errore durante la connessione a MongoDB:", errore);
}
};

modulo.exports = connectDB;

Definire il modello di dati

Nella directory principale, crea un nuovo file modello/utente.modello.js file e aggiungere il codice seguente per definire un modello di dati per i dati degli utenti utilizzando Mongoose.

cost mangusta = richiedere('mangusta');

cost utenteSchema = nuovo mangusta. Schema({
nome utente: Corda,
parola d'ordine: Corda,
ruolo: Corda
});

modulo.exports = mangusta.modello('Utente', userSchema);

Crea il controller per gli endpoint API

Crea un nuovo controllori/user.controller.js file nella directory principale e aggiungere il codice seguente.

Innanzitutto, effettua queste importazioni:

cost Utente = richiedere('../modelli/utente.modello');
cost passaporto = richiedere('passaporto');
cost { generateToken } = richiedere('../middleware/auth');
richiedere('../middleware/passaporto')(passaporto);

Successivamente, definire la logica per gestire la registrazione dell'utente e la funzionalità di accesso:

exports.registerUser = asincrono (req, res) => {
cost { nome utente, password, ruolo } = req.body;

Tentativo {
aspetta User.create({ nome utente, password, ruolo });
res.stato(201).json({ Messaggio: 'Utente registrato con successo' });
} presa (errore) {
consolare.log (errore);
res.stato(500).json({ Messaggio: 'Si è verificato un errore!' });
}
};

exports.loginUser = (req, res, successivo) => {
passaporto.authenticate('Locale', { sessione: falso }, (err, utente, info) => {
Se (errare) {
consolare.log (err);

ritorno res.stato(500).json({
Messaggio: 'Si è verificato un errore durante l'accesso'
});
}

Se (!utente) {
ritorno res.stato(401).json({
Messaggio: 'Credenziali di accesso non valide'
});
}

richiesta.login (utente, { sessione: falso }, (err) => {
Se (errare) {
consolare.log (err);

ritorno res.stato(500).json({
Messaggio: 'Si è verificato un errore durante l'accesso'
});
}

cost { _id, nome utente, ruolo } = utente;
cost carico utile = { ID utente: _id, nome utente, ruolo };
cost token = generateToken (carico utile);
res.cookie('gettone', gettone, { httpSolo: VERO });
ritorno res.stato(200).json({ Messaggio: 'Accesso riuscito' });
});
})(req, res, successivo);
};

IL registratiUtente La funzione gestisce la registrazione di un nuovo utente estraendo il nome utente, la password e il ruolo dal corpo della richiesta. Quindi crea una nuova voce utente nel database e risponde con un messaggio di successo o un errore se si verifica durante il processo.

D'altra parte, il loginUtente La funzione facilita l'accesso dell'utente utilizzando la strategia di autenticazione locale fornita da Passport.js. Autentica le credenziali dell'utente e restituisce un token in caso di accesso riuscito, che viene quindi memorizzato in un cookie per le successive richieste autenticate. Se si verificano errori durante il processo di accesso, verrà restituito un messaggio appropriato.

Infine, aggiungi il codice che implementa la logica recuperando tutti i dati degli utenti dal database. Useremo questo endpoint come percorso limitato per garantire che solo gli utenti autorizzati con il ruolo di admin può accedere a questo endpoint.

exports.getUsers = asincrono (req, res) => {
Tentativo {
cost utenti = aspetta Utente.find({});
res.json (utenti);
} presa (errore) {
consolare.log (errore);
res.stato(500).json({ Messaggio: 'Si è verificato un errore!' });
}
};

Impostare una strategia di autenticazione locale Passport.js

Per autenticare gli utenti dopo aver fornito le proprie credenziali di accesso, è necessario configurare una strategia di autenticazione locale.

Crea un nuovo middleware/passport.js file nella directory principale e aggiungere il seguente codice.

cost Strategia Locale = richiedere('passaporto locale').Strategia;
cost Utente = richiedere('../modelli/utente.modello');

modulo.esporta = (passaporto) => {
passaporto.uso(
nuovo Strategia locale(asincrono (nome utente, password, fatto) => {
Tentativo {
cost utente = aspetta User.findOne({ username });

Se (!utente) {
ritorno Fatto(nullo, falso);
}

Se (utente.password !== password) {
ritorno Fatto(nullo, falso);
}

ritorno Fatto(nullo, utente);
} presa (errore) {
ritorno fatto (errore);
}
})
);
};

Questo codice definisce una strategia passport.js locale per autenticare gli utenti in base al nome utente e alla password forniti.

All'inizio, interroga il database per trovare un utente con un nome utente corrispondente, quindi procede alla convalida della password. Di conseguenza, restituisce l'oggetto utente autenticato se il processo di accesso ha esito positivo.

Crea un middleware di verifica JWT

Dentro il middleware directory, creare un nuovo file auth.js e aggiungere il codice seguente per definire un middleware che genera e verifica JWT.

cost jwt = richiedere('jsonwebtoken');
cost secretKey = process.env. CHIAVE SEGRETA;

cost generareToken = (carico utile) => {
cost token = jwt.sign (payload, secretKey, { scade tra: '1h' });
ritorno gettone;
};

cost verificaToken = (richiestoRuolo) =>(req, res, successivo) => {
cost token = req.cookies.token;

Se (!gettone) {
ritorno res.stato(401).json({ Messaggio: "Nessun token fornito" });
}

jwt.verify (token, secretKey, (err, decodificato) => {
Se (errare) {
ritorno res.stato(401).json({ Messaggio: 'Gettone non valido' });
}

req.userId = decoded.userId;

Se (decoded.ruolo !== ruolo obbligatorio) {
ritorno res.stato(403).json({
Messaggio: 'Non hai l'autorizzazione e le autorizzazioni per accedere a questa risorsa.'
});
}

Prossimo();
});
};

modulo.exports = { generateToken, verificheToken };

IL generateToken la funzione crea un JWT con un tempo di scadenza specificato, mentre il verificaToken la funzione controlla se il token è presente e valido. Inoltre, verifica anche che il token decodificato contenga il ruolo richiesto, in sostanza, assicurando che abbiano accesso solo gli utenti con il ruolo e le autorizzazioni autorizzati.

Per firmare in modo univoco i JWT, devi generare una chiave segreta univoca e aggiungerla al tuo .env file come mostrato di seguito.

SECRET_KEY="Questa è una chiave segreta di esempio."

Definire le rotte API

Nella directory principale, crea una nuova cartella e chiamala route. All'interno di questa cartella, crea un nuovo file userRoutes.jse aggiungere il codice seguente.

cost espresso = richiedere('esprimere');
cost router = espresso. Router();
cost userController = richiedere('../controller/userController');
cost {verificareToken} = richiedere('../middleware/auth');

router.post('/API/registrati', userControllers.registerUser);
router.post('/api/accesso', userControllers.loginUser);

router.get('/api/utenti', verificaToken('amministratore'), userControllers.getUsers);

modulo.exports = router;

Questo codice definisce le route HTTP per un'API REST. IL utenti percorso specifico, server come percorso protetto. Limitando l'accesso agli utenti con il admin ruolo, applichi efficacemente il controllo degli accessi basato sui ruoli.

Aggiorna il file del server principale

Apri i tuoi server.js file e aggiornarlo come segue:

cost espresso = richiedere('esprimere');
cost cor = richiedere('cor');
cost cookieParser = richiedere('analisi dei cookie');
cost app = espresso();
cost porto = 5000;
richiedere('dotenv'.config();
cost connectDB = richiedere('./utils/db');
cost passaporto = richiedere('passaporto');
richiedere('./middleware/passaporto')(passaporto);

connettiDB();

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

cost userRoute = richiedere('./percorsi/percorsi utente');
app.use('/', userRoute);

app.listen (porta, () => {
consolare.tronco d'albero(`Il server è in esecuzione sulla porta ${porta}`);
});

Infine, avvia il server di sviluppo per eseguire l'applicazione.

nodo server.js

Sfrutta il meccanismo RBAC per migliorare i tuoi sistemi di autenticazione

L'implementazione del controllo degli accessi basato sui ruoli è un modo efficace per migliorare la sicurezza delle tue applicazioni.

Sebbene incorporare le librerie di autenticazione esistenti per stabilire un sistema RBAC efficiente sia un ottimo approccio, sfruttare le librerie RBAC per definire in modo esplicito i ruoli degli utenti e assegnare le autorizzazioni fornisce una soluzione ancora più solida, in definitiva, migliorando la sicurezza complessiva del tuo applicazione.