如何用Node.js进行JSON网络令牌认证

83 阅读5分钟

现在让我们通过使用JSON Web令牌来保护一些端点。什么是JWTs?JSON网络令牌是base64url编码的JSON对象,通过使用私钥进行加密。嵌入JWT的可以是一组或多组名称和值对。你可能有像用户ID或用户名这样的东西嵌入到令牌中。由于采用了加密技术,你无法看到这些数据,但它可以在服务器上被破译,因为应用程序可以使用私钥。如果你想了解所有的细节,JWT.io有一个很好的介绍。现在,让我们看看如何使用JSON网络令牌来保护我们Node API中的各种端点。


使用授权中间件

在我们刚刚为视频游戏系统的平台设置的路由和模型中,我们允许任何用户向修改服务器上数据的api发送post或put请求。事实上,除了简单的GET请求,几乎所有的操作都应该有某种类型的保护。现在让我们来设置一下。


1.添加一个中间件目录

首先,我们可以添加一个中间件目录来存放我们将要使用的授权中间件。
middleware directory node app


2.创建一个 auth.js 文件

我们正在创建一个新的 auth.js 文件,以存储读取请求头的逻辑,这样就可以在我们喜欢的任何端点上使用。
new authjs middleware file


3.添加代码以读取和验证JWT

在这个 auth.js 文件中,我们完成了几个步骤。首先,我们需要json web token和配置包。然后,我们设置了一个导出的函数,所以我们可以在其他地方随意使用。最后,我们确保逻辑已经到位,以读取令牌,并根据提供的令牌授予或拒绝访问。注意jwt.verify()函数的使用,它为我们完成了繁重的工作。


/middleware/auth.js

const jwt = require('jsonwebtoken');
const config = require('config');

module.exports = function (req, res, next) {

    const token = req.header('x-auth-token');
    if (!token) {
        return res.status(401).send('Access denied. No JWT provided.');
    }

    try {
        const decoded = jwt.verify(token, config.get('PrivateKey'));
        req.user = decoded;
        next();
    }
    catch (ex) {
        res.status(400).send('Invalid JWT.');
    }
}

用我们的新中间件保护路由

好了,我们创建了中间件,现在让我们来使用它!这很容易。这是很容易的。首先,我们要将Auth中间件应用到platform.js路由文件中的POST路由。我们所要做的就是要求新的Auth中间件,然后把它作为router.post()函数的第二个参数。
require auth middleware and apply to route


使用Postman测试Auth中间件

看起来一切都到位了,让我们发送一个POST请求到http://localhost:4000/api/platforms,而不提供任何令牌。
no token post request

到目前为止还不错,我们得到的错误是 "拒绝访问。没有提供JWT"。

现在,我们可以发送一个JSON网络令牌,但这是一个假的令牌。只是我们编造的一些愚蠢的东西。
invalid json web token in post request

现在我们想用一个有效的JWT做一个POST请求。因此,首先我们需要找到一个JWT来使用。我们可以通过检查由http://localhost:4000/api/users/ 端点生成的响应头来做到这一点。现在来看看这个。在我们的测试中使用这个之前,让我们看看如何解码JWT。你可以访问jwt.io/,并粘贴有关的token。然后,你也可以粘贴你自己的私钥。在我们的案例中,我们简单地称它为PrivateKey 。有了这个,我们可以验证令牌,也可以看到嵌入令牌的任何东西。
decode json web token at jwtio

这表明,5b3b8c70eb573812189785fe 的用户ID被嵌入到令牌中。现在谁在数据库中拥有这个用户ID呢?莫莫先生!
objectid found in jwt
这意味着Momo先生是一个有效的用户,他现在应该可以毫无问题地进行POST请求。我们喜欢莫莫先生。

好了,在这最后一个测试中,我们需要做几件事。首先,我们需要在发送给api的POST请求中包含JSON Web Token。如何做到这一点?很简单,只要在Postman中填入x-auth-token 字段。
x-auth-token post request

现在,由于我们要发布到http://localhost:4000/api/platforms,我们记得这将在服务器上创建一个新的平台。我们将像这样创建 "Android "平台。
json application data in body

现在是关键时刻!使用JWT和JSON有效载荷发送那个POST请求,创建一个新的平台。
successful post request using JWT

我们得到了一个响应,其中的JSON对象指定为 "Android"。这意味着什么呢?这意味着它成功了!不相信我?让我们也在Compass中看看。
new insert into mongodb worked


按你认为合适的方式应用auth中间件

这里是最棒的事情。我们得到了这个中间件的工作,并将其应用于一个特定的路由或端点。

回顾一下,这就像使用require来拉入中间件一样简单,像这样。

const auth = require('../middleware/auth');

然后,我们可以把它作为router.post()函数的第二个参数,像这样。

router.post('/', auth, async (req, res) => {}

这意味着你现在可以在任何你喜欢的地方使用它。例如,没有用户应该能够在没有经过验证的情况下删除一个平台。想给这个路由添加保护吗?很简单。

router.delete('/:id', auth, async (req, res) => {
    const platform = await Platform.findByIdAndRemove(req.params.id);

    if (!platform) {
        return res.status(404).send('That platform ID was not found');
    }

    res.send(platform);
});

用Node.js进行JSON网络令牌认证总结

有了这些,我们可以看到,通过使用JSON Web令牌,实现一个中间件来保护各种路由是非常直接的。如果用户试图在没有发送令牌的情况下进行请求,api应该以401状态代码响应,表示未授权。如果用户确实提供了一个有效的令牌,但没有正确的权限,api可以用403状态代码响应,表示被禁止。另外,不要在数据库中以纯文本形式存储JWT。最好是由客户端来存储JWT。在本教程中,JWT被简单地存储在Postman应用程序中进行测试。Postman本身是作为客户端的。在实际应用中,无论选择什么框架,都会有某种类型的客户端,JWT可以存储在那里。