Hapi 开发中 token 认证实现方案解析

在前端开发中,很多应用需要进行用户认证。其中,token 认证是其中一种较为常见的方案,它有许多优点,能够避免一些常见的安全问题。在 Hapi 开发中,实现 token 认证相对比较容易,本文将介绍如何在 Hapi 中实现 token 认证。

什么是 token 认证?

token 认证是一种常见的用户认证方式,它通过在请求头或请求体中携带一个 token(令牌)来进行认证。在用户登录成功后,服务端会生成一个 token 并返回给客户端,客户端将该 token 存入本地,以后每次请求时都将该 token 发送至服务端进行验证。当服务端接收到请求时,会从请求头或请求体中获取该 token 并进行验证,验证通过后即认为该请求是合法的。

token 认证在一些场景中有其优点,比如:

  • 易于维护:相比于传统的 session 认证,token 认证可以避免服务端存储 session 带来的问题。
  • 分布式应用:在分布式应用中,由于缺少共享存储,session 认证变得比较困难,而 token 认证不受此限制,能够很好地适用于分布式应用中。
  • 扩展性强:token 认证不需要在服务端存储任何东西,因此可以很好地适应服务端的扩展。

在 Hapi 中实现 token 认证的基本思路

在 Hapi 中实现 token 认证,可以选择使用 hapi-auth-jwt2 插件。该插件是官方推荐的 JWT 认证插件,支持 token 颁发和验证。

在进行 token 认证时,一般需要对以下内容进行验证:

  • 请求头或请求体中是否存在 token,并且 token 是否符合规范;
  • token 中包含的信息是否正确,比如用户 id、角色信息等;
  • token 的签发时间、过期时间是否有效。

基于以上验证需求,我们可以将 token 认证的基本思路描述如下:

  1. 用户登录时,服务端生成一个 token 并返回给客户端;
  2. 客户端将该 token 存入本地;
  3. 每次请求时,客户端将该 token 发送至服务端;
  4. 服务端从请求头或请求体中获取该 token,将其验证;
  5. 如果验证通过,则表示该请求是合法的,否则表示该请求是非法的。

下面将详细介绍如何在 Hapi 中实现该流程。

在 Hapi 中配置 hapi-auth-jwt2 插件

在使用 hapi-auth-jwt2 插件之前,需要先进行该插件的配置。在 Hapi 中,我们可以使用 server.register 方法来对插件进行注册,示例代码如下:

await server.register(require('hapi-auth-jwt2'));

server.auth.strategy('jwt', 'jwt', {
  key: 'your secret key',  // 签名密钥,可以是任意字符串,服务端和客户端要保持一致
  validate: async (decoded, request) => {
    // 根据 decoded 中包含的信息,来判断该 token 是否合法
    return { isValid: true };
  },
  verifyOptions: { algorithms: ['HS256'] },  // 加密算法
  cookieKey: 'token',  // 可选的 cookie 选项,如果存在,则代表 token 从 cookie 中获取
});

上述代码中,我们首先使用 server.register 方法对插件进行了注册。在插件被注册之后,我们可以使用 server.auth.strategy 方法来配置 authentication strategy(认证策略)。其中,我们使用了 jwt 策略,并指定了以下选项:

  • key:签名密钥,可以是任意字符串,服务端和客户端要保持一致;
  • validate:该选项是对 decode 后的信息进行验证的回调函数,我们可以在该函数中根据 decode 中的信息,来判断 token 是否合法。如果回调函数返回一个对象,且该对象的 isValid 属性为 true,则表示验证通过;
  • verifyOptions:加密算法,这里我们指定的是 HS256 算法;
  • cookieKey:可选的 cookie 选项,如果存在,则代表 token 从 cookie 中获取。

除了上述选项之外,我们还需要为每个需要进行权限控制的路由设置 authentication strategy。在 Hapi 中,我们可以使用路由配置的 config.auth 属性来指定当前路由需要使用哪种认证策略。示例代码如下:

server.route({
  method: 'GET',
  path: '/',
  handler: (request, h) => {
    return 'homepage';
  },
  config: {
    auth: 'jwt',
  },
});

在上述代码中,我们对 / 路由进行了配置,指定了该路由需要使用 jwt 认证策略。当客户端向 / 发送请求时,Hapi 会先进行 token 认证,如果认证通过,则返回该路由对应的处理函数。

在 Hapi 中生成 token 并返回给客户端

在登录成功后,我们需要生成一个 token 并返回给客户端。在 Hapi 中,我们可以使用 hapi-auth-jwt2 插件提供的 sign 方法来生成 token。示例代码如下:

const jwt = require('jsonwebtoken');

const token = jwt.sign({ id: 'user id', role: 'admin' }, 'your secret key', { expiresIn: '1h' });

在上述代码中,我们使用了 jwt.sign 方法来生成 token。其中,第一个参数是包含 token 信息的对象,我们可以将用户的一些基本信息放入该对象中。第二个参数是签名密钥,可以是任意字符串,服务端和客户端要保持一致。第三个参数是选项,其中 expiresIn 指定了 token 过期时间。

在生成 token 后,一般情况下需要将其返回给客户端。在 Hapi 中,我们可以使用 server.state 方法来设置 cookie。示例代码如下:

const token = jwt.sign({ id: 'user id', role: 'admin' }, 'your secret key', { expiresIn: '1h' });

return h.response({ message: 'login success' }).state('token', token);

在上述代码中,我们使用 h.response 方法返回了一个响应,其中 state 方法可以将 token 存入 cookie 中,这样客户端就能在以后的请求中使用该 token。

在 Hapi 中获取 token 并进行验证

在客户端发送请求时,我们需要将 token 发送至服务端。在 Hapi 中,我们可以从请求头或请求体中获取 token。示例代码如下:

const headers = request.headers;
const token = headers.authorization.split(' ')[1];

在上述代码中,我们首先从 request.headers 中获取请求头。然后,我们可以使用 authorization 字段来获取 token,并将其存入 token 变量中。

获取到 token 后,我们需要对其进行验证。在 Hapi 中,我们可以使用validate选项来进行验证。示例代码如下:

const validate = async (decoded, request) => {
  // 根据 decoded 中包含的信息,来判断该 token 是否合法
  return { isValid: true };
};

const res = await server.auth.test('jwt', request, { validate });

在上述代码中,我们使用 server.auth.test 方法来对 token 进行验证。其中,第一个参数是认证策略,这里我们指定了使用 jwt 策略。第二个参数是请求对象,即当前请求。第三个参数是一个选项对象,其中包含了 validate 方法,用于验证解密后的 token。

如果 token 验证通过,则返回值中包含一个 isValid 属性,值为 true。否则,该值为 false

总结

在本文中,我们介绍了如何在 Hapi 中实现 token 认证。首先,我们介绍了 token 认证的基本概念,以及其优点。接着,我们详细介绍了在 Hapi 中实现 token 认证的基本思路,并附上了示例代码。如果您正在进行 Hapi 开发,那么本文会对您有所帮助。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a22e26add4f0e0ffa3e02f


纠错反馈