使用 Passport.js 部分保护 API 端点

Posted

技术标签:

【中文标题】使用 Passport.js 部分保护 API 端点【英文标题】:Partially protect API endpoint with Passport.js 【发布时间】:2015-08-07 10:42:18 【问题描述】:

根据用户登录状态,我想从 SAME api 端点提供不同的结果。

用例是从相同的 api 端点提供文章。 所以有些文章是公开的,而有些是私人的。 还有专门的页面,可以查询文章列表。

示例: api/articles/special/all

此 API 应返回数据库中当前的所有页面。 但如果用户未登录,它也应该过滤掉私人结果。

使用 Passport.js 我只能保护整个 API 端点,例如:

router.get('/', auth.isAuthenticated(), controller.index);

虽然我想在实际函数中调用 auth.isAuthenticated() 方法,例如:

// Get list of articles
exports.index = function(req, res) 
  Article.find(function (err, articles) 
    if(err)  return handleError(res, err); 
    var titles = [];
    var loggedIn = false;
    if (auth.isAuthenticated()) loggedIn = true; // NOT WORKING
    for (var i = 0; i<articles.length; ++i) 
      if (articles[i].role === 'loggedIn' && loggedIn) 
          titles.push(articles[i].name);
       else if(articles[i].role !== 'loggedIn') 
        titles.push(articles[i].name);
      
    
    return res.json(200, titles);
  );
;

任何想法,如何在控制器内使用 Passport.js,而不是保护整个 API 端点?

【问题讨论】:

【参考方案1】:

我不确定如何使用 passport.js 来完成此操作,但如果您使用 Stormpath 之类的东西,开箱即用很容易完成。

一旦您初始化/配置了 express-stormpath 中间件,它将自动尝试对任何用户进行身份验证而不会让您显式使用中间件。

例如,你可以说:

var express = require('express');
var stormpath = require('express-stormpath');

var app = express();

app.use(stormpath.init(app));

app.get('/myapi', function(req, res) 
  if (req.user) 
    res.json( status: 'YOU ARE LOGGED IN: ' + req.user.email );
   else 
    res.json( status: 'YOU ARE NOT LOGGED IN!' );
  
);

app.listen(3000);

因为 Stormpath 为您存储用户,如果您使用 express-stormpath 库,这意味着它将尝试通过网络会话(在浏览器中)或用户的 API 密钥(Stormpath 也商店)。

这就是它工作起来非常简单的原因,因为中间件将检查传入的 HTTP 标头并使用 Basic Auth 或 OAuth2 正确验证用户 =)

【讨论】:

以上是关于使用 Passport.js 部分保护 API 端点的主要内容,如果未能解决你的问题,请参考以下文章

Passport.js本地策略如何保护路线

Express + Passport.js:req.user 未定义

Passport.js 可选身份验证

使用 passport.js、sails.js API 和 ember.js 登录 Facebook

使用 passport.js 和 express.js (node.js) 制作安全的 oauth API

Node.js - JWT、API:如何实现多个 Passport.js 身份验证中间件?