身份验证切换请求
¥Authentication Switch Request
在连接阶段,服务器可能会要求客户端切换到不同的身份验证方法。如果设置了 authPlugins
连接配置选项,它必须是一个对象,其中每个键都是服务器请求的潜在身份验证插件的名称,相应的值必须是一个可选接收连接配置选项并返回另一个函数的函数,该函数反过来可选接收切换请求数据。
¥During the connection phase the server may ask the client to switch to a different auth method.
If the authPlugins
connection config option is set, it must be an object where each key
is the name of a potential authentication plugin requested by the server, and the corresponding
value must be a function that optionally receives the connection config options and returns
another function, which in turn, optionally receives the switch request data.
插件加载了 ({user,password,...})
签名,每次调用都有 (pluginData)
签名。每次调用都应使插件返回任何额外的身份验证数据(Buffer
),这些数据应同步或使用 Promise
异步发送回服务器,或应相应地产生错误。
¥The plugin is loaded with a ({user,password,...})
signature, and each call has a (pluginData)
signature. Each call should make the plugin return any additional authentication data (Buffer
)
that should be sent back to the server, either synchronously or asynchronously using a Promise
,
or should yield an error accordingly.
示例:(虚构的 ssh-key-auth
插件)伪代码
¥Example: (imaginary ssh-key-auth
plugin) pseudo code
const conn = mysql.createConnection({
user: 'test_user',
password: 'test',
database: 'test_database',
authPlugins: {
'ssh-key-auth': function ({ password }) {
return function (pluginData) {
return getPrivate(key)
.then((key) => {
const response = encrypt(key, password, pluginData);
// continue handshake by sending response data
return response;
})
.catch((err) => {
// throw error to propagate error to connect/changeUser handlers
});
};
},
},
});
还有一个弃用的 API,如果设置了 authSwitchHandler
连接配置选项,它必须是接收切换请求数据并通过回调响应的函数。在这种情况下,第一次调用始终具有 ({pluginName, pluginData})
签名,随后调用 - ({pluginData})
。客户端通过 callback(null, data: Buffer)
响应与请求的插件匹配的不透明 blob。
¥There is also a deprecated API where if a authSwitchHandler
connection config option is set
it must be a function that receives switch request data and responds via a callback. In this case,
the first invocation always has a ({pluginName, pluginData})
signature, following calls - ({pluginData})
.
The client replies with an opaque blob matching the requested plugin via callback(null, data: Buffer)
.
const conn = mysql.createConnection({
user: 'test_user',
password: 'test',
database: 'test_database',
authSwitchHandler: function ({ pluginName, pluginData }, cb) {
if (pluginName === 'ssh-key-auth') {
getPrivateKey((key) => {
const response = encrypt(key, pluginData);
// continue handshake by sending response data
// respond with error to propagate error to connect/changeUser handlers
cb(null, response);
});
} else {
const err = new Error(
`Unknown AuthSwitchRequest plugin name ${pluginName}`
);
err.fatal = true;
cb(err);
}
},
});
初始握手始终使用 mysql_native_password
插件执行。这将有可能在未来版本中被覆盖。
¥The initial handshake is always performed using mysql_native_password
plugin. This will be possible to override in future versions.
请注意,如果请求 mysql_native_password
方法,它将根据 Authentication::Native41 在内部处理,并且不会调用任何 authPlugins
函数或 authSwitchHandler
。
¥Note that if the mysql_native_password
method is requested it will be handled internally according
to Authentication::Native41
and no authPlugins
function or the authSwitchHandler
will be invoked.
如果插件算法需要客户端和服务器之间多次往返数据交换,则可以多次调用这些函数。
¥These MAY be called multiple times if the plugin algorithm requires multiple roundtrips of data exchange between client and server.
多因素身份验证
¥Multi-factor authentication
如果用户需要服务器中的多因素身份验证,客户端将收到 AuthNextFactor
请求,该请求的结构与常规身份验证切换请求类似,包含附加身份验证因素插件(最多 3 个)的名称和可能的初始数据。可以使用连接配置选项提供其他密码 - password2
和 password3
。同样,对于每个身份验证因素,插件算法可能需要多次往返数据交换。
¥If the user requires multi-factor authentication in the server, the client will receive a AuthNextFactor
request, which is similar in structure to the regular authentication switch request and contains the name
and possible initial data for the additional authentication factor plugin (up to 3). Additional passwords
can be provided using the connection config options - password2
and password3
. Again, for each
authentication factor, multiple roundtrips of data exchange can be required by the plugin algoritm.
const conn = mysql.createConnection({
user: 'test_user',
password: 'secret1',
password2: 'secret2',
password3: 'secret3',
database: 'test_database',
authPlugins: {
// password1 === password
'auth-plugin1': function ({ password1 }) {
return function (serverPluginData) {
return clientPluginData(password1, serverPluginData);
};
},
'auth-plugin2': function ({ password2 }) {
return function (serverPluginData) {
return clientPluginData(password2, serverPluginData);
};
},
'auth-plugin3': function ({ password3 }) {
return function (serverPluginData) {
return clientPluginData(password3, serverPluginData);
};
},
},
});