为restify.js实现基于令牌的身份验证的最佳方法是什么?

use*_*712 12 authentication restful-authentication node.js restify

我正在尝试使用restify.js构建RESTful api,但我不想向所有人公开api.我将使用基于令牌的身份验证.我心中的过程是这样的,我不确定它是否合理.

  1. 用户向api发送用户名/密码以获取令牌.

  2. 这个令牌应该包含在每个其他api的调用请求中.

如果这是合理的,我可以使用任何node.js库吗?

另外,我该如何保护令牌?如果有人用令牌拦截了http请求,那么该人将获得api url和令牌.然后他可以按照自己的意愿发送请求.有办法避免这种情况吗?

非常感谢!

Gaj*_*jus 25

基本访问认证

Restify与authorizationParser插件捆绑在一起.authorizationParser解析出来Authorization.当插件正在使用时,它将提供req.usernamereq.authorization属性.后者的格式是:

{
  scheme: <Basic|Signature|...>,
  credentials: <Undecoded value of header>,
  basic: {
    username: $user
    password: $password
  }
}
Run Code Online (Sandbox Code Playgroud)

您的服务器需要有选择地拦截需要身份验证的请求并验证用户访问凭据.

这是一个示例服务器,需要对所有调用进行身份验证:

var restify = require('restify'),
    server;

server = restify.createServer();

server.use(restify.authorizationParser());

server.use(function (req, res, next) {
    var users;

    // if (/* some condition determining whether the resource requires authentication */) {
    //    return next();
    // }

    users = {
        foo: {
            id: 1,
            password: 'bar'
        }
    };

    // Ensure that user is not anonymous; and
    // That user exists; and
    // That user password matches the record in the database.
    if (req.username == 'anonymous' || !users[req.username] || req.authorization.basic.password !== users[req.username].password) {
        // Respond with { code: 'NotAuthorized', message: '' }
        next(new restify.NotAuthorizedError());
    } else {
        next();
    }

    next();
});

server.get('/ping', function (req, res, next) {
    res.send('pong');

    next();
});

server.listen(8080);
Run Code Online (Sandbox Code Playgroud)

最简单的测试方法是使用curl:

$ curl -isu foo:bar http://127.0.0.1:8080/ping

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 6
Date: Fri, 12 Dec 2014 10:52:17 GMT
Connection: keep-alive

"pong"

$ curl -isu foo:baz http://127.0.0.1:8080/ping

HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 37
Date: Fri, 12 Dec 2014 10:52:31 GMT
Connection: keep-alive

{"code":"NotAuthorized","message":""}
Run Code Online (Sandbox Code Playgroud)

Restify带有支持基本身份验证的内置JsonClient,例如

var restify = require('restify'),
    client;

client = restify.createJsonClient({
    url: 'http://127.0.0.1:8080'
});

client.basicAuth('foo', 'bar');

client.get('/ping', function(err, req, res, obj) {
    console.log(obj);
});
Run Code Online (Sandbox Code Playgroud)

OAuth 2.0

如果您更喜欢令牌身份验证,那么您可以使用restify-oauth2包实现Client Credentials身份验证流程,这就是您所追求的.

文档页面逐步介绍了如何设置此类身份验证,包括每个端点的角色,并在其存储库中有一个代码示例.

摘要

无论您选择哪种身份验证方法,所有这些方法都要求您使用HTTPS.不同之处在于,如果用户名/密码被泄露,用户将需要更改其凭据.如果令牌被泄露,则用户需要请求新令牌.后者可以通过编程方式完成,而前者通常依赖于硬编码值.

边注.在生产中,如果在不安全的通道上至少传输一次,例如受损的HTTPS,则必须将凭证视为"受损",如SSL错误,例如Heartbleed.