在前端开发中,很多应用需要进行用户认证。其中,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 认证的基本思路描述如下:
- 用户登录时,服务端生成一个 token 并返回给客户端;
- 客户端将该 token 存入本地;
- 每次请求时,客户端将该 token 发送至服务端;
- 服务端从请求头或请求体中获取该 token,将其验证;
- 如果验证通过,则表示该请求是合法的,否则表示该请求是非法的。
下面将详细介绍如何在 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