向Mean.io初学者解释Mean.io样本包的身份验证是如何工作的

时间:2014-08-18 05:42:48

标签: node.js express mean.io

我从mean.io学习this tutorial video,其中显示了示例包(由mean package mymodule创建。它也在"包"下描述docs)。我想帮助理解给定的身份验证/授权是如何工作的。

默认样本包/模块具有客户端上的简单用户身份验证

myapp / packages / mymodule / public / views / index.html 包含:

    <li>
      <a href="mymodule/example/anyone">Server route that anyone can access</a>
    </li>
    <li>
      <a href="mymodule/example/auth">Server route that requires authentication</a>
    </li>
    <li>
      <a href="mymodule/example/admin">Server route that requires admin user</a>
    </li>

在服务器端,

myapp / packages / mymodule / server / routes / mymodule.js ,包含:

// The Package is past automatically as first parameter
module.exports = function(Mymodule, app, auth, database) {

  app.get('/mymodule/example/anyone', function(req, res, next) {
    res.send('Anyone can access this');
  });

  app.get('/mymodule/example/auth', auth.requiresLogin, function(req, res, next) {
    res.send('Only authenticated users can access this');
  });

  app.get('/mymodule/example/admin', auth.requiresAdmin, function(req, res, next) {
    res.send('Only users with Admin role can access this');
  });

  ...
};

不同身份验证的神奇之处在于app.get()additional authentication callback的第二个参数:无,auth.requiresLoginauth.requiresAdmin

这是身份验证魔术(也在github上):

的myapp /包/访问/服务器/配置/ authorization.js

/**
 * Generic require login routing middleware
 */
exports.requiresLogin = function(req, res, next) {
  if (!req.isAuthenticated()) {
    return res.send(401, 'User is not authorized');
  }
  next();
};

/**
 * Generic require Admin routing middleware
 * Basic Role checking - future release with full permission system
 */
exports.requiresAdmin = function(req, res, next) {
  if (!req.isAuthenticated() || !req.user.hasRole('admin')) {
    return res.send(401, 'User is not authorized');
  }
  next();
};

问题A:为什么&#34; exports.requiresLogin&#34;和&#34; exports.requiresAdmin&#34;在authorization.js而不是&#34; somethingelse.requiresLogin&#34;和#34; somethingelse.requiresAdmin&#34;?这是&#34;出口&#34;与 myapp / packages / access / server / config / passport.js exportsmodule.exports = function(passport) { ...}github相关?如果是这样,我们在什么情况下可以使用这个&#34;出口&#34;?


由于身份验证的授权规则是在包中写入的,因此访问&#34;并且在包&#34; mymodule&#34;中使用,Mean.io包并不是彼此独立的。 Access包已在

上注册

myapp / packages / access / app.js github

var mean = require('meanio'),
  Module = mean.Module,
  passport = require('passport');

var Access = new Module('access');

Access.register(function(database) {

  // Register auth dependency

  var auth = require('./server/config/authorization');
  require('./server/config/passport')(passport);

  // This is for backwards compatibility
  mean.register('auth', function() {
    return auth;
  });

  mean.register('passport', function() {
    return passport;
  });

  Access.passport = passport;
  Access.middleware = auth;

  return Access;
});

问题B:Mean.io会自动链接所有软件包还是代码链接软件包?它是否由于部分与#34相关联;这是为了向后兼容&#34 ;如下所示?如果是这样,哪里可以&#34; auth&#34;使用?所有包 myapp / packages / ?在mean.io base app目录 myapp / 中怎么样?

var auth = require('./server/config/authorization');

// This is for backwards compatibility
  mean.register('auth', function() {
    return auth;
  });

问题C:为什么&#34; Access.passport = passport;&#34;,但&#34;中间件&#34; for&#34; Access.middleware = auth;&#34;?如果是&#34; Access.auth = auth&#34;会发生什么?

1 个答案:

答案 0 :(得分:0)

关于问题A(使用exports

在Node.js中,为exports对象赋值使这些值可用于require源文件的代码。

例如,给定文件foo.js

exports.foo = "FOO";
exports.bar = "BAR";

和档案main.js

var foo = require('foo.js');
console.log('foo=',foo.foo,'; bar=',foo.bar);

正在运行node main.js会输出foo= FOO ; bar= BAR

例如,请参阅Node's module documentationthis write-up on require and exports

关于问题B(关于包&#34;链接&#34;)

这个问题的答案是对问题A答案的补充。

有代码&#34;链接&#34;包裹。这是require声明。

在您的app.js源代码中,第一行(读取var mean = require('meanio'))会将局部变量mean设置为exports对象所指定的值meanio.js 1}}和/或meanio模块已加载。

passport = require('passport')相同。在这种情况下,加载index.js in the passport module后,局部变量passport将等于exports的值。

关于问题C

我不完全确定你在这里问的是什么,但是让我去试一试。

在这种情况下:

1){1}在第1行&#34;进口&#34; meanio模块,使局部变量var mean = require('meanio')或多或少设置为等于meanio模块中mean的值。

2)第2行中的exports设置局部变量Module = mean.Module等于Module的值,该值必须在meanio模块中分配。

3)mean.Module实例化var Access = new Module('access')类的实例,将其分配给局部变量Module

4)Access在名为Access.passport = passport的{​​{1}}实例中分配名为passport的实例变量(meanio.Module模块{{1}的值在第3行#)

5)Access在名为passport的{​​{1}}实例中分配名为require的实例变量(在第11行中由Access.middleware = auth返回的值)

我不熟悉&#34; meanio&#34;模块,但基于此代码,您似乎正在配置middleward实例(名为meanio.Module),方法是指定特定的&#34; magic&#34;变量名。

换句话说,您可能拥有Access或(而不是第5行)require('./server/config/authorization')而不是meanio.Module("access")

那就是&#34; meanio&#34;的作者模块似乎决定使用特殊的变量名来配置类而不是&#34; setter&#34;传递给构造函数的方法或参数。我假设在meanio代码中的某个位置,您会找到AccessAccess.passport = passport; Access.middleware = auth之类的引用,其中代码假定您已填充&#34;填充&#34;这些实例变量发生在代码示例的最后几行中。

如果您要添加Access.setPassport(passport); Access.setMiddleware(auth),那么所有会发生的事情是var Access = new Module('access',passport,auth)对象会有一个名为this.middleware的新属性,其等于局部变量this.passport的那个。

如果您使用Access.auth = auth 代替 Access,我会假设auth类中使用auth的任何代码1}}将失败,因为没有为Access.auth分配任何值,Access.middleware不是#34;魔法&#34; meanio正在寻找的变量名。