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

Posted

技术标签:

【中文标题】为 restify.js 实现基于令牌的身份验证的最佳方法是啥?【英文标题】:What is the best way to implement a token-based authentication for restify.js?为 restify.js 实现基于令牌的身份验证的最佳方法是什么? 【发布时间】:2013-08-27 01:02:12 【问题描述】:

我正在尝试使用 restify.js 构建一个 RESTful api,但我不想将 api 公开给所有人。我将使用基于令牌的身份验证。脑子里的流程是这样的,不知道合不合理。

    用户将用户名/密码发送到 api 以获取令牌。

    此令牌应包含在所有其他 api 调用的请求中。

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

另外,如何保护令牌?如果有人拦截了带有令牌的 http 请求,那么该人将获得 api url 和令牌。然后他可以根据需要发送请求。有没有办法避免这种情况?

非常感谢!

【问题讨论】:

如果你可以使用https,你就不会遇到这样的中间人攻击问题。只要你在 http 上,令牌就会被泄露。 谢谢。我听说使用 https 会有一些性能折衷。这是唯一的解决方案吗?关于我的另一个问题,node.js 中是否有用于基于令牌的身份验证的现有库?谢谢! passportjs.org 支持oauth 【参考方案1】:

Basic access authentication

Restify 与 authorizationParser 插件捆绑在一起。 authorizationParser 解析出Authorization。当插件在使用中时,它将使req.usernamereq.authorization 属性可用。后者的格式为:


  scheme: <Basic|Signature|...>,
  credentials: <Undecoded value of header>,
  basic: 
    username: $user
    password: $password
  

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

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

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

最简单的测试方法是使用 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":""

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

OAuth 2.0

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

文档页面逐步描述了如何设置此类身份验证,包括每个端点的角色,并且在其存储库中有一个code example。

总结

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

旁注。在生产环境中,如果通过不安全的通道(例如HTTPS 漏洞,如 SSL 漏洞,例如Heartbleed。

【讨论】:

应该把req.username改成req.authorization.basic.username 我如何应用这种方法来只验证某些路由但允许访问其他路由? @DeanMeehan 在不安全路由之后、安全路由之前添加 server.use 行。

以上是关于为 restify.js 实现基于令牌的身份验证的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

基于 Spring Security 令牌的身份验证

基于令牌的身份验证和哈希密码

如何使用 Apache Shiro 实现基于 JWT 令牌的身份验证机制?

用户和单独模块的基于令牌的身份验证

Web API 中基于令牌的身份验证,无需任何用户界面

基于令牌的身份验证的安全性