可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to write a REST-API server with NodeJS like the one used by Joyent, and everything is ok except I can't verify a normal user's authentication. If I jump to a terminal and do curl -u username:password localhost:8000 -X GET
, I can't get the values username:password on the NodeJS http server. If my NodeJS http server is something like
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");
, shouldn't I get the values username:password somewhere in the req object that comes from the callback ?
How can I get those values without having to use Connect's basic http auth ?
回答1:
The username:password is contained in the Authorization header as a base64-encoded string.
Try this:
http.createServer(function(req,res){
var header=req.headers['authorization']||'', // get the header
token=header.split(/\s+/).pop()||'', // and the encoded auth token
auth=new Buffer.from(token, 'base64').toString(), // convert from base64
parts=auth.split(/:/), // split on colon
username=parts[0],
password=parts[1];
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('username is "'+username+'" and password is "'+password+'"');
}).listen(1337,'127.0.0.1');
Detail on http authorization can be found at http://www.ietf.org/rfc/rfc2617.txt
回答2:
If you're using express, you can use the connect plugin (included with 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:
You can use node-http-digest for basic auth or everyauth, if adding authorization from external services are in you roadmap.
回答4:
I use this code for my own starter sites with auth.
It does several things:
- basic auth
- return index.html for / route
- serve content without crashing and silent handle the error
- allow port parameter when running
- minimal amount of logging
Before using the code, 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:
The restify framework (http://mcavage.github.com/node-restify/) includes an authorization header parser for "basic" and "signature" authentication schemes.
回答6:
You can use http-auth module
// 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);
回答7:
It can be implemented easily in pure node.js with no dependency, this is my version which is based on this answer for express.js but simplified so you can see the basic idea easily:
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');