Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何认证&;使用使用Passport.js的远程NodeJS API授权客户端Web应用程序_Javascript_Node.js_Api_Express_Passport.js - Fatal编程技术网

Javascript 如何认证&;使用使用Passport.js的远程NodeJS API授权客户端Web应用程序

Javascript 如何认证&;使用使用Passport.js的远程NodeJS API授权客户端Web应用程序,javascript,node.js,api,express,passport.js,Javascript,Node.js,Api,Express,Passport.js,如下图所示,我有一个独立的API项目运行在一个端口为3001的服务器上,还有一个Web应用程序运行在一个端口为3002的服务器上 端口3001上的API具有Web应用程序(和移动应用程序)获取和放置数据所需的所有API路由,包括身份验证API(使用passport local和passport jwt)。在项目的API方面,我还处理了用户角色授权,每个路由都有可以访问API的角色列表 示例路线 todoRoutes.get('/', requireAuth,

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

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

示例路线

todoRoutes.get('/', 
               requireAuth,
               AuthController.roleAuth(['user','editor','admin']),
               TodoController.getTodos);
端口3001中的角色授权API方法

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');

        });
    }
}
成功登录后的json响应如下

{
    "token": "JWT eyJhbGci...",
    "user": {
        "_id": "5986b81d940bab06ddc79b34",
        "email": "myemail@gmail.com",
        "role": "admin"
    }
}
现在,在Web App中,我想使用相同的角色授权和身份验证(登录),但您知道,Web App未连接到数据库,我可以进行诸如检查会话中的用户是否有效以及是否具有成功登录后得到的响应中的角色之类的查询

摘要 以下是我在这个问题中寻找的要点:

  • 通过端口3001上的远程API登录客户端Web应用程序(已实现)
  • 获取用户令牌和其他信息(如上所示的响应)(已实现)
  • 确保用户在客户端Web应用程序上经过身份验证,并记住用户loggedin的角色,以便使用这些信息对客户端应用程序上的每个路由进行授权。在客户端应用程序中,我有几个页面带有表单,可以将数据发送到端口3002上的服务器端API,这些页面由两个不同的用户使用,角色分别为editor和admin
  • 短暂性脑缺血发作


    }

    我认为有两种方法可以做到这一点,尽管并不完美

    一种是使用特定视图的主api端点。通常,每个视图都有一个主端点,如果该端点返回一个
    未授权
    /
    禁止
    状态,则不应渲染视图。但是这个解决方案有问题,并且并不总是有一个主端点匹配一个视图

    另一个选项是使用角色为路由命名,如
    admin/dashboard
    users/dashboard
    ,用户应该有一个描述其角色的字段,例如
    user.role
    。在呈现视图之前,检查API返回的url和用户对象中的相应角色

    第二个选项是首选的,这是我通常使用的


    希望能有所帮助。

    JWT的美丽不是已经解决了这个问题,还是可以通过正确的实现解决您的问题

    你所需要的只是

  • WebApp中初始化
    passport jwt
    模块,方法与在API中初始化模块相同,即
    secretrokey
    参数
  • 检查
    JWT
    ,特别是
    角色
    属性,并基于该属性允许/拒绝

  • 您的身份验证API应该返回一个嵌入了保证信息(角色)的JWT。此外,应该使用视图API已知的秘密创建令牌


    例如,使用npm模块,按如下方式签名:

    token = jwt.sign( {
        exp: Math.floor( Date.now() / 1000 ) + ( 60 * 60 ), // 1 hour
        i: user._id,
        role: user.role
    }, "my-secret" );
    
    然后,在视图API上,使用,它既验证令牌,又为您提供与您签名的原始对象匹配的有效负载。将有效负载用作用户对象:

    passport.use( new JwtStrategy( {
        secretOrKey: "my-secret"
    
    }, ( payload, callback ) => callback( null, payload ) ) );
    
    const authenticate = () =>
        passport.authenticate( "jwt", { session: false, failWithError: true } )
    
    在此阶段,您的用户至少经过身份验证。如果要将视图限制为某些角色,则应添加第二个中间件:

    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 );
    

    如果您的视图需要更多关于用户的信息,则身份验证API需要提供这些信息,无论是在JWT中(因此有保证)还是在外部(不保证,但会产生较小的令牌)。

    因此,API没有身份验证,但没有RBAC,但webapp希望实现RBAC。对吗?API有,身份验证和RBAC(适用于所有API),现在web app想要使用这些API和RBAC,web app的RBAC用于控制视图,而API的RBAC用于控制对控制器和读写数据的访问。明白了!我补充了一个答案。感谢您的解释。我无法理解您对这段代码的意思。在您的问题中,您提到您希望根据您的角色管理视图,我使用
    res.render
    所做的操作上面的代码在API服务器上,而API服务器不处理任何视图,还要检查路由是如何放置在主api服务器上的。感谢您的回答,我不明白如何使用它进行应用程序的整体身份验证。您能让我清楚一点吗?从您在问题中的新编辑中,我了解到您已经在API服务器中执行了基于角色的身份验证,现在您希望以某种方式使用它来限制客户端用户可访问的路由。有很多方法可以做到这一点。首先,如果客户端没有限制,API服务器应该始终将会话中的用户角色与端点所需的角色相匹配(您可以很容易地实现,如我的回答中所示)。其次,您还可以在客户端读取JWT等中的用户角色,防止呈现和形成其他角色用户的提交。您能用示例代码结构指导我吗,我无法理解
    secretrokey
    部分。另外,您能告诉我如何在客户端使用
    passport jwt
    ,而不必连接到
    User
    schema,或者在客户端应用程序上也必须有
    User
    schema。
    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 );