【问题标题】:How can I protect an API endpoint with PassportJS?如何使用 PassportJS 保护 API 端点?
【发布时间】:2013-11-28 19:03:22
【问题描述】:

我的应用使用 Express 和 AngularJS。我正在使用 express 来通过静态处理角度代码的基本 Web 服务。角度代码使用命中由 express 托管的 API 端点的服务。我只希望在用户通过身份验证后可以访问 API 端点。我怎样才能通过 PassportJS 做到这一点?

【问题讨论】:

  • 我不久前找到了一个关于该主题的链接,它可能会对您有所帮助。它不使用 PassportJS(而且我并不像我想的那样熟悉它),但您可以通过您已经在使用的 Express 进行身份验证。向下滚动到单路由身份验证部分(文章中的最后一个)。我发现这个例子非常简单,我相信你可以使用这种方法(或 PassportJS)来验证你的 API 的路由。链接:NODE.JS AND EXPRESS - BASIC AUTHENTICATION 如果你在 PassportJ 中发现了这个

标签: angularjs express passport.js


【解决方案1】:

我在 github 上上传了一个 Angular-Express project,我一直在努力。

它仍在进行中。希望对你有帮助。

它使用 PassportJs 进行用户身份验证,是服务器端授权的基本示例。它演示了如何使 API 调用仅对经过身份验证的用户或仅对具有管理员角色的用户可访问。这是在server/routes.js 调用ensureAuthenticatedensureAdmin 中定义的中间件函数server/authentication.js 中实现的

在 routes.js 中

// anybody can access this 
app.get('/api/test/users', 
        api.testUsers);


// only logged-in users with ADMIN role can access this 
app.get('/api/users',          
        authentication.ensureAdmin,
        api.testUsers);

// only logged-in users can access this
app.get('/api/books', 
        authentication.ensureAuthenticated, 
        api.books);

在 authentication.js 中

ensureAuthenticated: function(req, res, next) {
    if (req.isAuthenticated()) {
       return next();
    } else {
       return res.send(401);
    }
},

ensureAdmin: function(req, res, next) {
  // ensure authenticated user exists with admin role, 
  // otherwise send 401 response status
  if (req.user && req.user.role == 'ADMIN') {
      return next();
  } else {
      return res.send(401);
  }
},

【讨论】:

  • 在他们的文档中,PassportJs 给出了以下端点保护示例:app.get('/api/me',passport.authenticate('basic', { session: false }),function(req, res) {res.json(req.user);});passport.authenticate 实际上是做什么的?它检查用户是否经过身份验证或进行身份验证?
【解决方案2】:

我还没有使用passportjs,但我刚刚做了你想做的同样的事情。这是我的示例配置:

// Example configuration
var express = require('express');
var routes = require('./routes');
var app = express();

app.configure(function(){
    app.use(express.bodyParser());
    app.use(express.cookieParser('shhhh, very secret'));
    app.use(express.session());
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.compress());
    app.use('/', express.static(expressAppdir)); // look for overrides on express server 1st
    app.use('/', express.static(appDir));
   // app.use(express.methodOverride()); 
    app.use(app.router);

    app.use(function(req, res, next){
      var err = req.session.error
        , msg = req.session.success;
      delete req.session.error;
      delete req.session.success;
      res.locals.message = '';
      if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
      if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
      next();
    });

});

app.configure(function() {
    // gets
    app.get('/', routes.root);
    app.get('/login', routes.login);
    app.get('/logout', routes.logout);    

    app.get('/restricted/test/:slug', restrict, routes.restrictedGet); // must be last API route, slug is any request on the end of the routes that is requested.

    app.post('/login', routes.loginPost);
});

function restrict(req, res, next) {
  console.dir('restrict called');
  if (req.session.user) {
    next();
  } else {
    req.session.error = 'Access denied!';
    res.redirect('/login');
  }
}

//Routes.js file

// my dummy login (in a separate file)

var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

  passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
  }
));

exports.restrictedGet = function (req, res, next) {
  console.dir('reached restricted get');

  var slug = req.params.slug;
  console.dir(req.route);

  if(req.route.path.indexOf('test')!=-1)
  {
    namedQuery['testFunction'](req,res,next);
  }
  else
  {
    res.status(404).send('no route found. Route requested: ' + req.route.path);
  }

  // do something with your route here, check what's being appended to the slug and fire off the appropriate function.
};

exports.login = function(req, res, next) {
  res.sendfile(serverBase + "/static/public/login.html");
};

exports.logout = function(req, res, next) {
     req.session.destroy(function(){
      res.redirect('/');
    });
};

// this is where you would hook in your passportjs stuff to do hashing of inputted text and compare it to the hash stored in your db etc.
// I use my own simple authentication funciton right now as i'm just testing.

exports.loginPost = function(req, res, next) {
  authenticate(req.body.username, req.body.password, function(err, user){
    console.log('Reached login user: ', user);
    if (user) {
          // Regenerate session when signing in
          // to prevent fixation 
          req.session.regenerate(function(){

            req.session.user = user;
            req.session.success = 'Authenticated as ' + user.name
            + ' click to <a href="/logout">logout</a>. '
            + ' You may now access <a href="/restricted">/restricted</a>.';
              res.redirect('/');
            });
        } else {
          req.session.error = 'Authentication failed, please check your '
          + ' username and password.'
          + ' (use "tj" and "foobar")';
          res.json({success: false});
          res.redirect('/login');
        }
      });
};

// You could now do this with passport instead:
exports.loginPost = function(req, res, next) {
  passport.authenticate('local'), function(err, user){
    console.log('Reached login user: ', user);
    if (user) {
          // Regenerate session when signing in
          // to prevent fixation 
          req.session.regenerate(function(){

            req.session.user = user;
            req.session.success = 'Authenticated as ' + user.name
            + ' click to <a href="/logout">logout</a>. '
            + ' You may now access <a href="/restricted">/restricted</a>.';
              res.redirect('/');
            });
        } else {
          req.session.error = 'Authentication failed, please check your '
          + ' username and password.'
          + ' (use "tj" and "foobar")';
          res.json({success: false});
          res.redirect('/login');
        }
      };
};

function authenticate(name, pass, fn) {

  var user = { name:name, password: pass }
  return fn(null,user);

};

这是我从http://www.breezejs.com/samples/zzahttp://passportjs.org/guide/authenticate/获得大量代码的地方

希望这会有所帮助!

#

编辑

#

我忘了提及,对于角度方面,我只有一个简单的表单将用户和密码的值发回登录后端点,因为 getEndpoint 受到限制,快递应用程序将处理其余的身份验证和限制事情的一面给你。如果我能提供任何进一步的帮助,请不要犹豫。

【讨论】:

    【解决方案3】:

    这是检查用户是否登录的一种非常简单的方法。

    假设你设置了这样的中间件:

    const authMiddleware = (req, res, next) => {
        if(req.headers.authorization == undefined) { // or whatever auth strategy you're using
            req.isAuthenticated = false;
        }
        else {
            // your own code to fetch user
            req.isAuthenticated = true;
        }
    
        next();
    }
    
    app.use(authMiddleware);
    

    您可以创建另一个简单的中间件来限制某些路由:

    const checkIsAuth = (req, res, next) => {
        req.isAuthenticated ? next() : res.sendStatus(401);
    }
    
    router.get('/foo', checkIsAuth, fooController.getAll);
    

    【讨论】:

      【解决方案4】:

      我知道两种解决方案

      angular-client-side-authangular-http-auth

      你可以在 github 上找到它

      【讨论】:

        猜你喜欢
        • 2020-11-30
        • 2014-09-21
        • 1970-01-01
        • 2020-02-13
        • 2015-08-07
        • 2016-08-22
        • 1970-01-01
        • 2019-02-20
        • 2019-12-25
        相关资源
        最近更新 更多