如何使用使用Passport.js的远程NodeJS API对客户端Web应用程序进行身份validation和授权

如下图所示,我有一个运行在端口为3001的服务器上的独立API项目,并且我有一个运行在端口为3002的服务器上的Web应用程序。

Web APP到API的流程

接口3001上的API具有Web应用程序(和移动应用程序)获取和放置数据所需的所有API路由,包括身份validationAPI(使用passport-localpassport-jwt )。 在项目的API方面,我也处理了用户angular色授权,每个路由都有可以访问API的angular色列表。

示例路线

 todoRoutes.get('/', requireAuth, AuthController.roleAuth(['user','editor','admin']), TodoController.getTodos); 

angular色授权API方法在端口3001

 exports.roleAuth = function(roles){ return function(req, res, next){ var user = req.user; User.findById(user._id, function(err, foundUser){ if(err){ res.status(422).json({error: 'No user found.'}); return next(err); } if(roles.indexOf(foundUser.role) > -1){ return next(); } res.status(401).json({error: 'You are not authorized to view this content'}); return next('Unauthorized'); }); } } 

login成功后响应json是这样的

 { "token": "JWT eyJhbGci...", "user": { "_id": "5986b81d940bab06ddc79b34", "email": "myemail@gmail.com", "role": "admin" } } 

现在在Web应用程序中 ,我想使用相同的angular色授权和身份validation(login),但是您看到,Web应用程序没有连接到数据库,对于我来说,查询会话中的用户是否有效并且具有login成功后得到的响应。

总结下面是我在这个问题中寻找的要点:

  1. 通过端口3001上的远程API在客户端Web应用程序上login(已实现)
  2. 获取用户令牌和其他信息( 上面显示的响应 )(达到)
  3. 确保用户在客户端Web应用程序上进行身份validation,并记住用户login的angular色,以使用这些信息来授权客户端应用程序中的每个路由。 在客户端应用程序中,我有几个表单向端口3002上的服务器端API发送数据,这些页面由两个不同的用户使用angular色编辑器pipe理员

TIA

您的身份validationAPI应该返回一个JWT,其中embedded了有保证的信息(angular色)。 此外,令牌应该使用您的视图API已知的秘密。


例如,使用npm模块jsonwebtoken ,像这样签名:

 token = jwt.sign( { exp: Math.floor( Date.now() / 1000 ) + ( 60 * 60 ), // 1 hour i: user._id, role: user.role }, "my-secret" ); 

然后,在您的视图API上,使用passport-jwt ,它们都会validation令牌,并为您提供与您签名的原始对象匹配的有效内容。 使用有效载荷作为用户对象:

 passport.use( new JwtStrategy( { secretOrKey: "my-secret" }, ( payload, callback ) => callback( null, payload ) ) ); const authenticate = () => passport.authenticate( "jwt", { session: false, failWithError: true } ) 

在这个阶段,您的用户至less需要通过身份validation。 如果你想限制视图到某些angular色,你可以添加第二个中间件:

 const assertRole = ( ...roles ) => ( req, res, next ) => req.user && roles.includes( req.user.role ) ? next() : res.sendStatus( 403 ) ); todoRoutes.get("/admin/view1", authenticate, assertRole( "user", "editor", "admin" ), TodoController.getTodos ); 

如果您的视图将需要更多关于用户的信息,authenticationAPI将需要在JWT(并因此保证)或外部(不保证,但是导致较小的令牌)中提供该信息。

 exports.roleAuth = function(roles){ return function(req, res, next){ var user = req.user; User.findById(user._id, function(err, foundUser){ if(err){ res.render('index.html'); } if(roles.indexOf(foundUser.role) > -1){ res.render('another.html'); } res.render('another2.html'); }); } 

}

有两种方法可以完成,虽然不完美。

一个是使用特定视图的主要API端点。 通常每个视图都有一个主要端点,如果该端点返回一个Unauthorized / Forbidden状态,则不应该渲染该视图。 但是这个解决scheme有问题,并不总是有一个匹配视图的主要端点。

其他选项是命名空间与angular色的路线,如admin/dashboardusers/dashboard ,用户应该有一个字段描述他们的angular色,例如。 user.role 。 在渲染视图之前,请检查API返回的url和user对象中的相应angular色。

第二个选项是首选,这是我一般使用的。

希望能帮助到你。

JWT的美不是已经解决了这个问题,还是可以通过正确的实施来解决你的问题?

所有这一切都是为了你

  1. 在您的WebApp中初始化passport-jwt模块的方式与您在API中初始化它的方式相同,即secretOrKey参数。
  2. 检查JWT ,特别是role属性,并根据这个属性来允许/拒绝