【问题标题】:Basic HTTP authentication in Node.JS?Node.JS 中的基本 HTTP 身份验证?
【发布时间】:2011-08-22 12:48:43
【问题描述】:

我正在尝试使用 NodeJS 编写一个 REST-API 服务器,就像 Joyent 使用的那样,一切都很好,除了我无法验证普通用户的身份验证。如果我跳转到终端并执行curl -u username:password localhost:8000 -X GET,我无法在 NodeJS http 服务器上获取值 username:password。如果我的 NodeJS http 服务器类似于

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, "127.0.0.1");

,我不应该在来自回调的 req 对象中的某处获取值 username:password 吗? 如何在不使用 Connect's basic http auth 的情况下获得这些值?

【问题讨论】:

  • console.dir(req.headers)
  • console.dir(req.headers) 仅输出 { 授权:'Basic am9hb2plcm9uaW1vOmJsYWJsYWJsYQ==','user-agent':'curl/7.21.3 (x86_64-pc-linux-gnu) libcurl /7.21.3 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18',主机:'localhost:8000',接受:'/'}
  • Express 4 见this answer

标签: http authentication node.js basic-authentication


【解决方案1】:

用户名:密码包含在授权标头中作为 base64 编码字符串

试试这个:

const http = require('http');
 
http.createServer(function (req, res) {
  var header = req.headers.authorization || '';       // get the auth header
  var token = header.split(/\s+/).pop() || '';        // and the encoded auth token
  var auth = Buffer.from(token, 'base64').toString(); // convert from base64
  var parts = auth.split(/:/);                        // split on colon
  var username = parts.shift();                       // username is first
  var password = parts.join(':');                     // everything else is the password
 
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('username is "' + username + '" and password is "' + password + '"');
}).listen(1337, '127.0.0.1');

来自HTTP Authentication: Basic and Digest Access Authentication - Part 2 Basic Authentication Scheme (Pages 4-5)

Backus-Naur 形式的基本身份验证

basic-credentials = base64-user-pass
base64-user-pass  = <base64 [4] encoding of user-pass,
                    except not limited to 76 char/line>
user-pass   = userid ":" password
userid      = *<TEXT excluding ":">
password    = *TEXT

【讨论】:

  • 别忘了解析出“Basic”,即:'Basic abcdef0123456789' === req.headers.authorization
  • 示例中的第三行已经通过在空白处拆分标题以产生 ["Basic","abcdef0123456789"] 并弹出最后一个值,这将是授权令牌来实现这一点。跨度>
  • 使用 express.basicAuth 方法来处理所有问题要好得多。更简单、更清洁。
  • 同意,但 OP 不希望这样做。
  • 如果密码包含冒号,这可能会失败。
【解决方案2】:

如果您使用的是 express,则可以使用 connect 插件(包含在 express 中):

//Load express
var express = require('express');

//User validation
var auth = express.basicAuth(function(user, pass) {     
   return (user == "super" && pass == "secret");
},'Super duper secret area');

//Password protected area
app.get('/admin', auth, routes.admin);

【讨论】:

【解决方案3】:

如果您在路线图中添加来自外部服务的授权,您可以使用 node-http-digest 进行基本身份验证或 everyauth

【讨论】:

    【解决方案4】:

    我将此代码用于我自己的带有身份验证的入门网站。

    它做了几件事:

    • 基本认证
    • 为/路由返回 index.html
    • 提供内容而不会崩溃并静默处理错误
    • 运行时允许端口参数
    • 最少的日志记录

    在使用代码之前,npm install express

    var express = require("express");
    var app = express();
    
    //User validation
    var auth = express.basicAuth(function(user, pass) {     
         return (user == "username" && pass == "password") ? true : false;
    },'dev area');
    
    /* serves main page */
    app.get("/", auth, function(req, res) {
    try{
        res.sendfile('index.html')
    }catch(e){}
    });
    
    /* add your other paths here */
    
    /* serves all the static files */
    app.get(/^(.+)$/, auth, function(req, res){ 
    try{
        console.log('static file request : ' + req.params);
        res.sendfile( __dirname + req.params[0]); 
    }catch(e){}
    });
    
    var port = process.env.PORT || 8080;
    app.listen(port, function() {
        console.log("Listening on " + port);
    });
    

    【讨论】:

      【解决方案5】:

      它可以在纯 node.js 中轻松实现,没有依赖关系,这是我的版本,它基于 this answer for express.js 但经过简化,因此您可以轻松看到基本思想:

      var http = require('http');
      
      http.createServer(function (req, res) {
          var userpass = new Buffer((req.headers.authorization || '').split(' ')[1] || '', 'base64').toString();
          if (userpass !== 'username:password') {
              res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="nope"' });
              res.end('HTTP Error 401 Unauthorized: Access is denied');
              return;
          }
          res.end('You are in! Yay!');
      }).listen(1337, '127.0.0.1');
      

      【讨论】:

        【解决方案6】:

        restify 框架 (http://mcavage.github.com/node-restify/) 包括用于“基本”和“签名”身份验证方案的授权标头解析器。

        【讨论】:

          【解决方案7】:

          你可以使用http-auth模块

          // Authentication module.
          var auth = require('http-auth');
          var basic = auth.basic({
              realm: "Simon Area.",
              file: __dirname + "/../data/users.htpasswd" // gevorg:gpass, Sarah:testpass ...
          });
          
          // Creating new HTTP server.
          http.createServer(basic, function(req, res) {
              res.end("Welcome to private area - " + req.user + "!");
          }).listen(1337);
          

          【讨论】:

            猜你喜欢
            • 2011-11-12
            • 1970-01-01
            • 2020-09-04
            • 2021-03-21
            • 2011-05-05
            • 1970-01-01
            • 1970-01-01
            • 2023-04-07
            • 1970-01-01
            相关资源
            最近更新 更多