向 Mean.io 初学者解释 Mean.io 示例包的身份验证如何工作

Posted

技术标签:

【中文标题】向 Mean.io 初学者解释 Mean.io 示例包的身份验证如何工作【英文标题】:Explain to Mean.io beginner how Mean.io sample package's authentication works 【发布时间】:2014-10-10 23:49:30 【问题描述】:

我从this tutorial video 学习mean.io,它显示了示例包(由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/packages/access/server/config/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:为什么在 authorization.js 中是“exports.requiresLogin”和“exports.requiresAdmin”而不是“somethingelse.requiresLogin”和“somethingelse.requiresAdmin”?这是“exports”吗? " 与 myapp/packages/access/server/config/passport.jsexports: module.exports = function(passport) ..., github?如果可以,在什么情况下我们可以使用这个“出口”?


由于认证的授权规则是写在“access”包中并用在“mymodule”包中的,所以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 是否会自动链接所有包,或者是否有代码将包链接到某个地方? 是否由于下面显示的“这是为了向后兼容”部分而链接的?如果是这样,“auth”可以在哪里使用?所有的包myapp/packages/?在mean.io基础应用目录myapp/怎么样?

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

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

问题 C:为什么它是“Access.passport = passport;”,而“Access.middleware = auth;”是“middleware”?如果是“Access.auth =授权”?

【问题讨论】:

exports 而言,这是 Node 模块系统的一部分。每当您require 某事时,您都会从所需文件中获得exports 对象。 关于问题 A,请参阅***.com/questions/5311334/… 【参考方案1】:

关于问题 A(关于使用 exports

在 Node.js 中,将值分配给 exports 对象使这些值可用于 requires 源文件的代码。

例如,给定文件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 documentation 或 this write-up on require and exports

关于问题 B(关于包“链接”)

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

有“链接”包的代码。这是require 语句。

在您的app.js 源代码中,第一行(读取var mean = require('meanio'))将设置局部变量mean 为分配给exports 对象的任何值是meanio.js 和/或meanio模块已加载。

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

关于问题 C

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

在这种情况下:

1) 第 1 行中的var mean = require('meanio')“导入”meanio 模块,使得局部变量mean 或多或少地设置为等于meanio 模块中exports 的值。

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

3) var Access = new Module('access') 正在实例化Module 类的一个实例,并将其分配给局部变量Access

4) Access.passport = passport 在名为 Accessmeanio.Module 实例中分配名为 passport 的实例变量(赋值给第 3 行的 passport 模块 required 的值)

5) Access.middleware = auth 在名为 Accessmeanio.Module 的实例中分配名为 middleward 的实例变量(赋值给第 11 行中 require('./server/config/authorization') 返回的值)。

我不熟悉“meanio”模块,但根据此代码,您似乎正在通过分配特定的“魔术”变量名称来配置 meanio.Module("access") 实例(名为 Access)。

换句话说,您可能有Access.setPassport(passport); Access.setMiddleware(auth) 或(而不是第5 行)var Access = new Module('access',passport,auth),而不是Access.passport = passport; Access.middleware = auth

也就是说,“meanio”模块的作者似乎决定使用特殊的变量名来配置类,而不是“setter”方法或传递给构造函数的参数。我假设在 meanio 代码的某处,您会找到对 this.middlewarethis.passport 之类的引用,其中代码假设您已经“填充”了这些实例变量,就像代码示例的最后几行中发生的那样.

如果您要添加Access.auth = auth,那么将会发生的只是Access 对象将具有一个名为auth 的新属性,其 等于局部变量的值auth.

如果你使用Access.auth 而不是 of Access.middleware,我假设Access 类中使用this.middleware 的任何代码都会失败,因为没有值曾经被分配给Access.middleware,而Access.auth 不是meanio 正在寻找的“神奇”变量名之一。

【讨论】:

以上是关于向 Mean.io 初学者解释 Mean.io 示例包的身份验证如何工作的主要内容,如果未能解决你的问题,请参考以下文章

扩展 mean.io 的用户包

未捕获的 ReferenceError:未定义角度 - Mean.IO

mean.io - 错误:“请求实体太大”。如何在meanio模块之外增加bodyParser限制?

在mean.io堆栈中表达js分页

mean.io 堆栈角长运行操作与 http 请求

MEAN IO:需要配置验证错误 JWT_SECRET