node.js - nodejs - Autenticación HTTP básica con Node y Express 4
nodejs server example (8)
Parece que implementar la autenticación HTTP básica con Express v3 era trivial:
app.use(express.basicAuth(''username'', ''password''));
La versión 4 (estoy usando 4.2) eliminó el middleware basicAuth
, así que estoy un poco atascado. Tengo el siguiente código, pero no hace que el navegador solicite credenciales al usuario, que es lo que me gustaría (y lo que imagino que hizo el método anterior):
app.use(function(req, res, next) {
var user = auth(req);
if (user === undefined || user[''name''] !== ''username'' || user[''pass''] !== ''password'') {
res.writeHead(401, ''Access invalid for user'', {''Content-Type'' : ''text/plain''});
res.end(''Invalid credentials'');
} else {
next();
}
});
Autenticación básica simple con JavaScript vanilla (ES6)
app.use((req, res, next) => {
// -----------------------------------------------------------------------
// authentication middleware
const auth = {login: ''yourlogin'', password: ''yourpassword''} // change this
// parse login and password from headers
const b64auth = (req.headers.authorization || '''').split('' '')[1] || ''''
const [login, password] = new Buffer(b64auth, ''base64'').toString().split('':'')
// Verify login and password are set and correct
if (!login || !password || login !== auth.login || password !== auth.password) {
res.set(''WWW-Authenticate'', ''Basic realm="401"'') // change this
res.status(401).send(''Authentication required.'') // custom message
return
}
// -----------------------------------------------------------------------
// Access granted...
next()
})
¿Por qué?
-
req.headers.authorization
contiene el valor "Basic <base64 string>
", pero también puede estar vacío y no queremos que falle, de ahí el extraño combo de|| ''''
|| ''''
- El nodo no conoce
atob()
ybtoa()
, de ahí elBuffer
ES6 -> ES5
const
es solo var
.. tipo de
(x, y) => {...}
es solo function(x, y) {...}
const [login, password] = ...split()
es solo dos asignaciones var
en una
fuente de inspiración (usa paquetes)
Lo anterior es un ejemplo súper simple que fue diseñado para ser súper corto y rápidamente desplegable en el servidor de tu patio de recreo. Pero como se señaló en los comentarios, las contraseñas también pueden contener caracteres de dos puntos:
Para extraerlo correctamente de b64auth , puede usar esto. // parse login and password from headers
const b64auth = (req.headers.authorization || '''').split('' '')[1] || ''''
const strauth = new Buffer(b64auth, ''base64'').toString()
const splitIndex = strauth.indexOf('':'')
const login = strauth.substring(0, splitIndex)
const password = strauth.substring(splitIndex + 1)
Por otro lado, si solo usa uno o muy pocos inicios de sesión, este es el mínimo indispensable que necesita:
(no es necesario analizar las credenciales)
//btoa(''yourlogin:yourpassword'') -> "eW91cmxvZ2luOnlvdXJwYXNzd29yZA=="
// Verify login and password is correct
if (req.headers.authorization !== ''Basic eW91cmxvZ2luOnlvdXJwYXNzd29yZA=='') {
// ...send(''Authentication required.'')
return
}
Por cierto, ¿necesita tener caminos seguros y "públicos"? Considere usar express.router
lugar.
var securedRoutes = require(''express'').Router()
securedRoutes.use(/* auth-middleware from above */)
securedRoutes.get(''path1'', /* ... */)
app.use(''/secure'', securedRoutes)
app.get(''public'', /* ... */)
// example.com/public // no-auth
// example.com/secure/path1 // requires auth
TL; DR:
☒ express.basicAuth
se ha ido
☒ basic-auth-connect
está en desuso
☒ basic-auth
no tiene ninguna lógica
☒ http-auth
es una exageración
☑ express-basic-auth
es lo que quieres
Más información:
Como usa Express, puede usar el middleware express-basic-auth
.
Ver los documentos:
Ejemplo:
const app = require(''express'')();
const basicAuth = require(''express-basic-auth'');
app.use(basicAuth({
users: { admin: ''supersecret123'' },
challenge: true // <--- needed to actually show the login dialog!
}));
Cambié en Express 4.0 la autenticación básica con http-auth , el código es:
var auth = require(''http-auth'');
var basic = auth.basic({
realm: "Web."
}, function (username, password, callback) { // Custom authentication method.
callback(username === "userName" && password === "password");
}
);
app.get(''/the_url'', auth.connect(basic), routes.theRoute);
Express ha eliminado esta funcionalidad y ahora recomienda usar la biblioteca de jshttp/basic-auth .
Aquí hay un ejemplo de cómo usar:
var http = require(''http'')
var auth = require(''basic-auth'')
// Create server
var server = http.createServer(function (req, res) {
var credentials = auth(req)
if (!credentials || credentials.name !== ''aladdin'' || credentials.pass !== ''opensesame'') {
res.statusCode = 401
res.setHeader(''WWW-Authenticate'', ''Basic realm="example"'')
res.end(''Access denied'')
} else {
res.end(''Access granted'')
}
})
// Listen
server.listen(3000)
Para enviar una solicitud a esta ruta, debe incluir un encabezado de Autorización formateado para la autenticación básica.
Para enviar primero una solicitud de curl, debe tomar la codificación base64 del name:pass
o en este caso aladdin:opensesame
que es igual a YWxhZGRpbjpvcGVuc2VzYW1l
Su solicitud de curl se verá así:
curl -H "Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l" http://localhost:3000/
Gran parte del middleware se extrajo del núcleo Express en v4 y se colocó en módulos separados. El módulo básico de autenticación está aquí: https://github.com/expressjs/basic-auth-connect
Tu ejemplo solo necesitaría cambiar a esto:
var basicAuth = require(''basic-auth-connect'');
app.use(basicAuth(''username'', ''password''));
Parece haber varios módulos para hacer eso, algunos están en desuso.
Este se ve activo:
jshttp/basic-auth
Aquí hay un ejemplo de uso:
// auth.js
var auth = require(''basic-auth'');
var admins = {
''[email protected]'': { password: ''pa$$w0rd!'' },
};
module.exports = function(req, res, next) {
var user = auth(req);
if (!user || !admins[user.name] || admins[user.name].password !== user.pass) {
res.set(''WWW-Authenticate'', ''Basic realm="example"'');
return res.status(401).send();
}
return next();
};
// app.js
var auth = require(''./auth'');
var express = require(''express'');
var app = express();
// ... some not authenticated middlewares
app.use(auth);
// ... some authenticated middlewares
Asegúrese de poner el middleware de auth
en el lugar correcto, cualquier middleware anterior no será autenticado.
Podemos implementar la autorización básica sin necesidad de ningún módulo
//1.
var http = require(''http'');
//2.
var credentials = {
userName: "vikas kohli",
password: "vikas123"
};
var realm = ''Basic Authentication'';
//3.
function authenticationStatus(resp) {
resp.writeHead(401, { ''WWW-Authenticate'': ''Basic realm="'' + realm + ''"'' });
resp.end(''Authorization is needed'');
};
//4.
var server = http.createServer(function (request, response) {
var authentication, loginInfo;
//5.
if (!request.headers.authorization) {
authenticationStatus (response);
return;
}
//6.
authentication = request.headers.authorization.replace(/^Basic/, '''');
//7.
authentication = (new Buffer(authentication, ''base64'')).toString(''utf8'');
//8.
loginInfo = authentication.split('':'');
//9.
if (loginInfo[0] === credentials.userName && loginInfo[1] === credentials.password) {
response.end(''Great You are Authenticated...'');
// now you call url by commenting the above line and pass the next() function
}else{
authenticationStatus (response);
}
});
server.listen(5050);
Fuente: - http://www.dotnetcurry.com/nodejs/1231/basic-authentication-using-nodejs
basicAuth
el código para la basicAuth
original para encontrar la respuesta:
app.use(function(req, res, next) {
var user = auth(req);
if (user === undefined || user[''name''] !== ''username'' || user[''pass''] !== ''password'') {
res.statusCode = 401;
res.setHeader(''WWW-Authenticate'', ''Basic realm="MyRealmName"'');
res.end(''Unauthorized'');
} else {
next();
}
});