随着 Web 技术的发展,用户认证已成为前端领域中非常重要的一环。在前端开发中,常常需要实现多种认证策略,比如本地认证、第三方认证(GitHub、Facebook等)、单点登录等等。本文将介绍使用 Hapi 和 Passport.js 实现多种认证策略的方法及示例代码。
Hapi 能力简介
Hapi 是一个万能的 Node.js Web 框架,支持多种 Web 开发场景。Hapi 具有以下优点:
- 多样化的路由 策略:支持自定义路由策略,在安全和性能方面有很大的优势。
- 配置简单:Hapi 框架非常简单易用,可以让你快速搭建一个实用的 Web 系统。
- 插件管理:支持多种插件,能够满足各种需求,扩展性非常好。
Passport.js 能力简介
Passport.js 是一个非常流行的 Node.js 认证库,常常用于 Web 开发中的身份验证。Passport.js 的主要优点有:
- 多种认证策略:提供本地认证、GitHub 等第三方认证以及单点登录等多种认证方式。
- 可配置性强:可以方便地自定义策略和创建可重用的策略。
- 扩展性强:具有许多插件,可以很方便地添加新的策略支持。
实现多种认证策略
假设我们需要实现本地认证和 GitHub 认证两种策略。下面我们来逐步完成认证的操作。
- 安装 Hapi 和 Passport.js
npm install hapi passport passport-local passport-github
- 定义本地策略
const passport = require('passport'); const LocalStrategy = require('passport-local'). Strategy; passport.use( new LocalStrategy( { usernameField: 'username', passwordField: 'password' }, (username, password, done) => { if (username === 'admin' && password === 'admin') { return done(null, { username: 'admin' }); } else { return done(null, false, '用户名或密码错误'); } } ) );
在上面的代码中,我们使用 passport-local
模块的 LocalStrategy
策略来实现本地认证。在 LocalStrategy
构造函数中,我们传入了一个包含 usernameField
和 passwordField
的配置对象。这里的 username
和 password
就是从前端传递进来的用户信息。如果用户名和密码正确,就返回用户信息,否则返回 false 和提示信息。
- 在 Hapi 中注册本地策略
在 Hapi 应用中注册 Passport.js,在路由处理之前调用 Passport.js 的 initialize()
方法和 session()
方法即可。通过调用 passport.authenticate('local')
进行本地认证,并在认证通过后调用 req.login()
方法存储用户信息。
const Hapi = require('hapi'); const passport = require('passport'); const server = new Hapi.Server(); server.connection({ port: 3000 }); server.register(require('hapi-auth-cookie'), err => { server.auth.strategy('session', 'cookie', { cookie: { password: 'password-should-be-32-characters', isSecure: false }, redirectTo: '/login', redirectOnTry: false, appendNext: true, ttl: 24 * 60 * 60 * 1000 }); server.register(require('hapi-auth-basic'), err => { server.auth.strategy('simple', 'basic', { validateFunc: (request, username, password, callback) => callback(null, true, { username, password }) }); }); server.register(require('bell'), err => { server.auth.strategy('github-oauth', 'bell', { provider: 'github', password: 'password-should-be-32-characters', clientId: '<client-id>', clientSecret: '<client-secret>', isSecure: false, location: 'http://localhost:3000' }); }); server.register(require('vision'), err => { server.views({ engines: { html: require('handlebars') }, path: __dirname + '/views', layout: 'layouts/main', partialsPath: 'views/partials' }); }); server.register(require('inert'), err => {}); server.ext('onPreResponse', function(request, reply){ if (request.response.isBoom) { const { statusCode, payload } = request.response.output; if (statusCode === 401) { console.log(payload.message); } } return reply.continue(); }); server.route([ { method: 'GET', path: '/login', config: { auth: false, handler: (request, reply) => { return reply.view('login'); } } }, { method: 'POST', path: '/local', config: { auth: { strategy: 'session', mode: 'try' }, handler: (request, reply) => { passport.authenticate('local', (err, user, message) => { if (err || !user) { return reply({ message }); } request.login(user, err => { if (err) { return reply(err); } return reply({ message: '认证成功' }); }); })(request, reply); } } }, { method: 'GET', path: '/github', config: { auth: 'github-oauth', handler: (request, reply) => { if (!request.auth.isAuthenticated) { return reply('认证失败'); } return reply.redirect('/'); } } }, { method: 'GET', path: '/me', config: { auth: 'session', handler: (request, reply) => { reply(request.auth.credentials); } } } ]); server.start(err => { if (err) { console.log(err); } console.log(`Server running at: ${server.info.uri}`); }); });
在上面的代码中,我们通过 hapi-auth-cookie
插件注册了 Passport.js,同时为认证设置了 cookie。通过调用 server.auth.strategy()
方法并传入插件名称和策略名称,完成了身份认证的注册。
在路由处理中,为 GET /login 注册了不需要认证的的策略。并创建了用于处理本地认证的 POST /local 路由。在 POST /local 中,首先使用 LocalStrategy 进行本地认证,如果认证通过,就使用 req.login()
方法存储用户信息。最后我们定义了 GET /me,该路由需要使用 session 策略进行认证,返回用户信息。GET /github 是用于处理 GitHub 认证的路由,需要使用 bell
插件进行认证。
- 在 Hapi 中注册 GitHub 认证
首先在 GitHub 中创建应用,并获取 clientId 和 clientSecret。随后在服务器端注册策略并在路由中使用该策略进行认证。在下面的代码中,我们使用 passport-github
模块的 GitHubStrategy
策略实现 GitHub 认证,通过调用 server.auth.strategy('github-oauth')
方法,在服务启动时注册 GitHub 策略。最后在 GET /github 路由中使用 bell
插件的 bell.authenticate()
方法进行认证。
- 测试
我们可以使用 POSTMAN 进行测试。当请求 POST /local 时,传入如下请求体:
{ "username": "admin", "password": "admin" }
返回如下信息,表示本地认证成功:
{ "message": "认证成功" }
当请求 GET /me 时,返回认证用户的信息:
{ "username": "admin" }
当请求 GET /github 时,跳转到 GitHub 认证页面,认证成功后会重定向到 / 页面,认证失败则会返回“认证失败”信息。
总结
通过本文的介绍,我们学习了如何使用 Hapi 和 Passport.js 实现多种认证策略。当然,认证策略不止本地认证和 GitHub 认证,我们可以根据需求来自定义策略。总之,了解并掌握认证是前端开发中非常重要的一环,同时也是一项必备技能。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/659f6f1badd4f0e0ff80e823