Базовая аутентификация HTTP с узлом и Экспресс 4
похоже, что реализация базовой HTTP-аутентификации с помощью Express v3 была тривиальной:
app.use(express.basicAuth('username', 'password'));
версия 4 (я использую 4.2) удалил basicAuth
middleware, хотя, так что я немного застрял. У меня есть следующий код, но он не заставляет браузер запрашивать у пользователя учетные данные, что я и хотел бы (и что я думаю, что старый метод сделал):
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();
}
});
8 ответов:
много промежуточного программного обеспечения было вытащено из ядра Express в v4 и помещено в отдельные модули. Основной модуль auth находится здесь:https://github.com/expressjs/basic-auth-connect
ваш пример просто нужно изменить для этого:
var basicAuth = require('basic-auth-connect'); app.use(basicAuth('username', 'password'));
простой основной Auth с ванильным JavaScript (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() })
почему?
req.headers.authorization
содержит значение "Basic <base64 string>
", но он также может быть пустым, и мы не хотим, чтобы это плохо, отсюда и странная комбинация|| ''
- узел не знаю
atob()
иbtoa()
, отсюдаBuffer
ES6 - > ES5
const
это простоvar
.. род из(x, y) => {...}
это простоfunction(x, y) {...}
const [login, password] = ...split()
дваvar
задания в одномисточник вдохновения (использует пакеты)
Выше-это супер просто пример, который должен был быть супер короткие и быстро развертывается на сервере игровой площадки. Но как было указано в комментариях, пароли также могут содержать символы двоеточия:
. Чтобы правильно извлечь его из b64auth, вы можете использовать это.// 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)
С другой стороны, если вы когда-либо используете только один или очень мало Логинов, это самый минимум, что вам нужно:
(вам не нужно анализировать учетные данные)//btoa('yourlogin:yourpassword') -> "eW91cmxvZ2luOnlvdXJwYXNzd29yZA==" // Verify login and password is correct if (req.headers.authorization !== 'Basic eW91cmxvZ2luOnlvdXJwYXNzd29yZA==') { // ...send('Authentication required.') return }
кстати, вам нужно иметь как безопасные, так и" общедоступные " пути? Рассмотрите возможность использования
express.router
вместо этого.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
Я изменил в express 4.0 обычную аутентификацию с http-auth, код:
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);
я использовал код для оригинальной
basicAuth
найти ответ: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(); } });
там, кажется, несколько модулей, чтобы сделать это, некоторые из них устарели.
этот выглядит активным:
https://github.com/jshttp/basic-authвот пример использования:
// auth.js var auth = require('basic-auth'); var admins = { 'art@vandelay-ind.org': { 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
убедитесь, что вы поставить
auth
промежуточное программное обеспечение в правильном месте, любое промежуточное программное обеспечение до этого не будет аутентифицироваться.
TL; DR:
☒
express.basicAuth
нет
☒basic-auth-connect
осуждается
☒basic-auth
не имеет никакой логики
☒http-auth
- это перебор
☑express-basic-auth
то, что вы хотитеПодробнее:
так как вы используете Экспресс, то вы можете использовать
express-basic-auth
middleware.посмотреть документы:
пример:
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! }));
мы можем реализовать базовую авторизацию без необходимости какого-либо модуля
//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);
источник:http://www.dotnetcurry.com/nodejs/1231/basic-authentication-using-nodejs
Express удалил эту функцию и теперь рекомендует использовать basic-auth библиотека.
вот пример того, как использовать:
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)
для отправки запроса на этот маршрут необходимо включить заголовок отформатирован для basic авторизации.
отправив запрос curl сначала вы должны взять base64 кодирование
name:pass
или в данном случаеaladdin:opensesame
что равноYWxhZGRpbjpvcGVuc2VzYW1l
ваш curl запрос будет выглядеть так:
curl -H "Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l" http://localhost:3000/