注:截止本文完成时,hapi 的版本为:16.4.3
在看 hapi 官方教程之前,建议先看这篇:
上面这篇教程相比官方教程来说讲解的更细致,不过原文中的代码是有 bug 的,正确的代码如下:
'use strict';
var Hapi = require('hapi')
var Bcrypt = require('bcrypt')
var BasicAuth = require('hapi-auth-basic')
// hardcoded users object … just for illustration purposes
var users = {
future: {
id: '1',
username: 'future',
password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG' // 'studio'
}
}
// create new server instance
var server = new Hapi.Server()
//教程中的代码遗忘了 connection 设定。
server.connection({
port: 3000,
host: 'localhost'
});
// register plugins to server instance
server.register(BasicAuth, function(err) {
if (err) {
throw err
}
// validation function used for hapi-auth-basic
var basicValidation = function(request, username, password, callback) {
var user = users[username]
if (!user) {
return callback(null, false)
}
Bcrypt.compare(password, user.password, function(err, isValid) {
//教程中将 user.username 写为了 user.name
callback(err, isValid, {
id: user.id,
name: user.username
})
})
}
//教程中的代码将“simple”写成了“basic”
//第一个参数,也就是“simple”可以是任意的名字,该名字只是为了便于后续的调用。
server.auth.strategy('simple', 'basic', {
validateFunc: basicValidation
})
server.route({
method: 'GET',
path: '/private-route',
config: {
auth: 'simple',
handler: function(request, reply) {
const id = request.auth.credentials.id;
const name = request.auth.credentials.name;
reply('欢迎回来!' + name + ',你的 id 是:' + id);
}
}
})
// start your server after plugin registration
server.start(function(err) {
if (err) {
throw err
}
console.log('info', 'Server running at: ' + server.info.uri)
})
})
代码运行后,访问 http://localhost:3000/private-route, 用 future/studio 分别作为账号、密码登录。
写到这里必须发一下牢骚,自我断断续续学习 hapi 半个月以来,越发感觉 hapi 官方的教程很鸡肋。理由在于官方教程往往就是扔出一个例子,然后就开始罗列 API 文档中的内容;而初学者面对一堆返回值和配置参数根本不知道从而谈起,反而越看越糊涂。
牢骚归牢骚,这里推荐 https://futurestud.io/ 上的 hapi 系列教程,以及在其教程中提及的范例代码。
Hapi 的官方教程中只提及了 basic 认证,而对于基于 cookie 的认证没有提及。如果想要学习的话可以参考:
尤其是这个范例项目,不但细致的呈现了具体的方法,而其对于代码的组织形式也很值得初学者借鉴。
这里提示一句,在阅读范例项目时会涉及一些与 hapi-auth-cookie 插件相关的 config 参数,这些参数的说明可以在 https://github.com/hapijs/hapi-auth-cookie 的 README.md 中找到。
根据官方教程中的解说,mode 参数可以为:
但是在官方的 API 文档中,又省去了 true 和 false 这2个参数。这一点我还不太明白,待考证。之所以去掉这2个参数,应该是它们仅针对 server.auth.strategy 有效,而对于单独的 route 配置不适用。
另外一个让我困惑的就是 'optional' 和 'try' 之间的区别。
网络上有人这么解释:
optional: no authentication credentials needed, but if provided they need to be valid
try: if the user provides invalid authentication credentials they still get accepted and users will proceed to the route handler
这个解释其实并不比 API 文档中说的更明白。