node.js Node 和 Express 4 的基本 HTTP 身份验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23616371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 17:20:10  来源:igfitidea点击:

Basic HTTP authentication with Node and Express 4

node.jshttpexpresshttp-authentication

提问by Dov

It looks like implementing basic HTTP authentication with Express v3 was trivial:

看起来使用 Express v3 实现基本的 HTTP 身份验证很简单:

app.use(express.basicAuth('username', 'password'));

Version 4 (I'm using 4.2) removed the basicAuthmiddleware, though, so I'm a little stuck. I have the following code, but it doesn't cause the browser to prompt the user for credentials, which is what I'd like (and what I imagine the old method did):

不过,版本 4(我使用的是 4.2)删除了basicAuth中间件,所以我有点卡住了。我有以下代码,但它不会导致浏览器提示用户输入凭据,这正是我想要的(以及我想象的旧方法所做的):

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();
    }
});

采纳答案by Dov

I used the code for the original basicAuthto find the answer:

我使用原始代码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();
    }
});

回答by Qwerty

Simple Basic Auth with vanilla JavaScript (ES6)

使用 vanilla 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] = Buffer.from(b64auth, 'base64').toString().split(':')

  // Verify login and password are set and correct
  if (login && password && login === auth.login && password === auth.password) {
    // Access granted...
    return next()
  }

  // Access denied...
  res.set('WWW-Authenticate', 'Basic realm="401"') // change this
  res.status(401).send('Authentication required.') // custom message

  // -----------------------------------------------------------------------

})

note: This "middleware" can be used in any handler. Just remove next()and reverse the logic. See the 1-statementexample below, or the edit historyof this answer.

注意:这个“中间件”可以在任何处理程序中使用。只需删除next()并反转逻辑即可。请参阅下面的1 语句示例,或此答案的编辑历史记录

Why?

为什么?

  • req.headers.authorizationcontains the value "Basic <base64 string>", but it can also be empty and we don't want it to fail, hence the weird combo of || ''
  • Node doesn't know atob()and btoa(), hence the Buffer
  • req.headers.authorization包含值“ Basic <base64 string>”,但它也可以为空,我们不希望它失败,因此奇怪的组合|| ''
  • Node 不知道atob()and btoa(),因此Buffer

ES6 -> ES5

ES6 -> ES5

constis just var.. sort of
(x, y) => {...}is just function(x, y) {...}
const [login, password] = ...split()is just two varassignments in one

const只是var...那种
(x, y) => {...}只是function(x, y) {...}
const [login, password] = ...split(),只不过是两个var在一个任务

source of inspiration (uses packages)

灵感来源(使用包)



以上是一个 super simple旨在成为的超级简单示例super short超短且可快速部署到您的游乐场服务器。但正如评论中指出的那样,密码也可以包含冒号字符::。正确地从b64authb64auth,您可以使用它。

  // parse login and password from headers
  const b64auth = (req.headers.authorization || '').split(' ')[1] || ''
  const strauth = Buffer.from(b64auth, 'base64').toString()
  const splitIndex = strauth.indexOf(':')
  const login = strauth.substring(0, splitIndex)
  const password = strauth.substring(splitIndex + 1)

  // using shorter regex by @adabru
  // const [_, login, password] = strauth.match(/(.*?):(.*)/) || []

Basic auth in one statement

一份声明中的基本身份验证

...on the other hand, if you only ever use one or very few logins, this is the bare minimum you need: (you don't even need to parse the credentials at all)

...另一方面,如果您只使用一次或很少登录,这是您需要的最低限度:(您甚至根本不需要解析凭据)

function (req, res) {
//btoa('yourlogin:yourpassword') ->?"eW91cmxvZ2luOnlvdXJwYXNzd29yZA=="
//btoa('otherlogin:otherpassword') -> "b3RoZXJsb2dpbjpvdGhlcnBhc3N3b3Jk"

  // Verify credentials
  if (  req.headers.authorization !== 'Basic eW91cmxvZ2luOnlvdXJwYXNzd29yZA=='
     && req.headers.authorization !== 'Basic b3RoZXJsb2dpbjpvdGhlcnBhc3N3b3Jk')        
    return res.status(401).send('Authentication required.') // Access denied.   

  // Access granted...
  res.send('hello world')
  // or call next() if you use it as middleware (as snippet #1)
}


PS: do you need to have both "secure" and "public" paths? Consider using express.routerinstead.

PS:你需要同时拥有“安全”和“公共”路径吗?考虑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

回答by rsp

TL;DR:

特尔;博士:

? express.basicAuthis gone
? basic-auth-connectis deprecated
? basic-authdoesn't have any logic
? http-authis an overkill
? express-basic-authis what you want

? express.basicAuth没了
basic-auth-connect已弃用
basic-auth没有逻辑
http-auth是矫枉过正
吗?express-basic-auth是你想要的

More info:

更多信息:

Since you're using Express then you can use the express-basic-authmiddleware.

由于您使用的是 Express,因此您可以使用express-basic-auth中间件。

See the docs:

查看文档:

Example:

例子:

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!
}));

回答by Brian Prodoehl

A lot of the middleware was pulled out of the Express core in v4, and put into separate modules. The basic auth module is here: https://github.com/expressjs/basic-auth-connect

很多中间件在 v4 中被从 Express 核心中拉出来,并放入单独的模块中。基本身份验证模块在这里:https: //github.com/expressjs/basic-auth-connect

Your example would just need to change to this:

您的示例只需要更改为:

var basicAuth = require('basic-auth-connect');
app.use(basicAuth('username', 'password'));

回答by WarsClon

I changed in express 4.0 the basic authentication with http-auth, the code is:

我在 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);

回答by Michael

There seems to be multiple modules to do that, some are deprecated.

似乎有多个模块可以做到这一点,有些已被弃用。

This one looks active:
https://github.com/jshttp/basic-auth

这个看起来很活跃:https:
//github.com/jshttp/basic-auth

Here's a use example:

这是一个使用示例:

// 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

Make sure you put the authmiddleware in the correct place, any middleware before that will not be authenticated.

确保将auth中间件放在正确的位置,在此之前的任何中间件都不会被验证。

回答by VIKAS KOHLI

We can implement the basic authorization without needing any module

我们可以实现基本授权,不需要任何模块

//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);

Source:- http://www.dotnetcurry.com/nodejs/1231/basic-authentication-using-nodejs

来源:- http://www.dotnetcurry.com/nodejs/1231/basic-authentication-using-nodejs

回答by Loourr

Express has removed this functionality and now recommends you use the basic-authlibrary.

Express 已删除此功能,现在建议您使用basic-auth库。

Here's an example of how to use:

以下是如何使用的示例:

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)

To send a request to this route you need to include an Authorization headerformatted for basic auth.

要向此路由发送请求,您需要包含一个为基本身份验证设置格式的Authorization 标头

Sending a curl request first you must take the base64encoding of name:passor in this case aladdin:opensesamewhich is equal to YWxhZGRpbjpvcGVuc2VzYW1l

首先发送 curl 请求,您必须采用或 在这种情况下等于的base64编码name:passaladdin:opensesameYWxhZGRpbjpvcGVuc2VzYW1l

Your curl request will then look like:

您的 curl 请求将如下所示:

 curl -H "Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l" http://localhost:3000/