在现代 Web 应用开发中,安全认证和授权是非常重要的一环。Hapi 是一个 Node.js 的 Web 应用框架,它提供了一系列的插件和工具来帮助我们实现安全认证和授权。本文将介绍 Hapi 中的安全认证和授权机制,以及如何在实际项目中应用它们。
安全认证
安全认证是指验证用户身份的过程。在 Hapi 中,我们可以使用多种插件来实现安全认证。其中比较常见的有 hapi-auth-basic、hapi-auth-cookie、hapi-auth-jwt2 等。
hapi-auth-basic
hapi-auth-basic 是 Hapi 中最简单的安全认证插件,它实现了 HTTP 基本认证。HTTP 基本认证是指客户端向服务器发送一个包含用户名和密码的请求头,服务器通过验证这些信息来确定用户身份。
使用 hapi-auth-basic 插件需要先安装:
npm install hapi-auth-basic
然后在 Hapi 应用中注册插件:
// www.javascriptcn.com code example
const Hapi = require('hapi');
const server = new Hapi.Server({ port: 3000 });
const users = {
john: {
username: 'john',
password: 'password123',
name: 'John Doe',
id: '2133d32a'
}
};
const validate = async (request, username, password, h) => {
const user = users[username];
if (!user) {
return { credentials: null, isValid: false };
}
const isValid = password === user.password;
const credentials = { id: user.id, name: user.name };
return { isValid, credentials };
};
const init = async () => {
await server.register(require('hapi-auth-basic'));
server.auth.strategy('simple', 'basic', { validate });
server.route({
method: 'GET',
path: '/',
config: {
auth: 'simple',
handler: (request, h) => {
return `Welcome ${request.auth.credentials.name}!`;
}
}
});
await server.start();
console.log(`Server running at: ${server.info.uri}`);
};
init();上面的例子中,我们定义了一个用户对象 users,其中包含一个用户名为 john 的用户。在 validate 函数中,我们检查请求头中的用户名和密码是否匹配 users 中的用户信息,如果匹配则返回 isValid 为 true,并将用户信息存储在 credentials 中。
在应用中,我们使用 server.auth.strategy 方法来定义一个认证策略。在这个例子中,我们定义了一个名为 simple 的策略,使用 basic 插件,并将 validate 函数作为验证函数。在路由中,我们使用 auth 配置项来指定使用 simple 认证策略。
当客户端发送一个请求到根路径时,会触发路由处理函数。由于路由配置中指定了 auth 选项为 simple,因此请求会被 simple 认证策略处理。如果认证成功,路由处理函数返回欢迎信息,否则返回 401 状态码。
hapi-auth-cookie
hapi-auth-cookie 插件实现了基于 Cookie 的认证。它允许我们使用 Cookie 来保存用户身份信息,从而不需要在每个请求中都发送用户名和密码。
使用 hapi-auth-cookie 插件需要先安装:
npm install hapi-auth-cookie
然后在 Hapi 应用中注册插件:
// www.javascriptcn.com code example
const Hapi = require('hapi');
const server = new Hapi.Server({ port: 3000 });
const users = {
john: {
username: 'john',
password: 'password123',
name: 'John Doe',
id: '2133d32a'
}
};
const validate = async (request, session) => {
const user = users[session.id];
if (!user) {
return { valid: false };
}
return { valid: true, credentials: user };
};
const init = async () => {
await server.register(require('hapi-auth-cookie'));
server.auth.strategy('session', 'cookie', {
cookie: {
name: 'sid-example',
password: 'password-should-be-32-characters',
isSecure: false
},
validateFunc: validate
});
server.route({
method: 'GET',
path: '/',
config: {
auth: 'session',
handler: (request, h) => {
return `Welcome ${request.auth.credentials.name}!`;
}
}
});
await server.start();
console.log(`Server running at: ${server.info.uri}`);
};
init();在上面的例子中,我们定义了一个用户对象 users,并定义了一个 validate 函数来验证用户身份。在 validate 函数中,我们根据 Cookie 中存储的用户 ID 来查找用户信息,如果找到了则返回 valid 为 true,并将用户信息存储在 credentials 中。
在应用中,我们使用 server.auth.strategy 方法来定义一个认证策略。在这个例子中,我们定义了一个名为 session 的策略,使用 cookie 插件,并将 validate 函数作为验证函数。在路由中,我们使用 auth 配置项来指定使用 session 认证策略。
当客户端发送一个请求到根路径时,会触发路由处理函数。由于路由配置中指定了 auth 选项为 session,因此请求会被 session 认证策略处理。如果认证成功,路由处理函数返回欢迎信息,否则返回 401 状态码。
hapi-auth-jwt2
hapi-auth-jwt2 插件实现了基于 JSON Web Token (JWT) 的认证。JWT 是一种用于身份验证的开放标准,它使用 JSON 对象来描述用户身份信息,并使用数字签名来保证数据的完整性和安全性。
使用 hapi-auth-jwt2 插件需要先安装:
npm install hapi-auth-jwt2
然后在 Hapi 应用中注册插件:
// www.javascriptcn.com code example
const Hapi = require('hapi');
const server = new Hapi.Server({ port: 3000 });
const users = {
john: {
username: 'john',
password: 'password123',
name: 'John Doe',
id: '2133d32a'
}
};
const validate = async (decoded, request, h) => {
const user = users[decoded.id];
if (!user) {
return { isValid: false };
}
return { isValid: true, credentials: user };
};
const init = async () => {
await server.register(require('hapi-auth-jwt2'));
server.auth.strategy('jwt', 'jwt', {
key: 'secret',
validate,
verifyOptions: { algorithms: ['HS256'] }
});
server.route({
method: 'GET',
path: '/',
config: {
auth: 'jwt',
handler: (request, h) => {
return `Welcome ${request.auth.credentials.name}!`;
}
}
});
await server.start();
console.log(`Server running at: ${server.info.uri}`);
};
init();在上面的例子中,我们定义了一个用户对象 users,并定义了一个 validate 函数来验证用户身份。在 validate 函数中,我们根据 JWT 中存储的用户 ID 来查找用户信息,如果找到了则返回 isValid 为 true,并将用户信息存储在 credentials 中。
在应用中,我们使用 server.auth.strategy 方法来定义一个认证策略。在这个例子中,我们定义了一个名为 jwt 的策略,使用 jwt 插件,并将 validate 函数作为验证函数。在路由中,我们使用 auth 配置项来指定使用 jwt 认证策略。
当客户端发送一个请求到根路径时,会触发路由处理函数。由于路由配置中指定了 auth 选项为 jwt,因此请求会被 jwt 认证策略处理。如果认证成功,路由处理函数返回欢迎信息,否则返回 401 状态码。
授权
授权是指验证用户是否有权限访问某个资源的过程。在 Hapi 中,我们可以使用 hapi-authorization 插件来实现授权。
使用 hapi-authorization 插件需要先安装:
npm install hapi-authorization
然后在 Hapi 应用中注册插件:
// www.javascriptcn.com code example
const Hapi = require('hapi');
const server = new Hapi.Server({ port: 3000 });
const users = {
john: {
username: 'john',
password: 'password123',
name: 'John Doe',
id: '2133d32a',
scope: ['admin']
}
};
const validate = async (decoded, request, h) => {
const user = users[decoded.id];
if (!user) {
return { isValid: false };
}
return { isValid: true, credentials: user };
};
const init = async () => {
await server.register([
require('hapi-auth-jwt2'),
require('hapi-authorization')
]);
server.auth.strategy('jwt', 'jwt', {
key: 'secret',
validate,
verifyOptions: { algorithms: ['HS256'] }
});
server.auth.default('jwt');
server.route({
method: 'GET',
path: '/',
config: {
auth: {
access: { scope: ['admin'] }
},
handler: (request, h) => {
return `Welcome ${request.auth.credentials.name}!`;
}
}
});
await server.start();
console.log(`Server running at: ${server.info.uri}`);
};
init();在上面的例子中,我们在用户对象中添加了一个 scope 属性,用于表示用户的权限。在 validate 函数中,我们将用户对象存储在 credentials 中,以便在授权时使用。
在应用中,我们使用 server.auth.default 方法来定义默认的认证策略。在这个例子中,我们将默认的认证策略设置为 jwt。在路由中,我们使用 auth 配置项来指定需要的权限。在这个例子中,我们指定了需要 admin 权限才能访问根路径。
当客户端发送一个请求到根路径时,会触发路由处理函数。由于路由配置中指定了需要 admin 权限,因此请求会被 hapi-authorization 插件处理。如果用户拥有 admin 权限,路由处理函数返回欢迎信息,否则返回 403 状态码。
结语
本文介绍了 Hapi 中的安全认证和授权机制,并提供了使用示例。在实际项目中,我们可以根据需求选择合适的认证和授权插件,并使用 server.auth.strategy 方法来定义认证策略。使用 hapi-authorization 插件可以轻松实现授权功能。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d0b2a3e46428fe9edfe267