Skip to main content

身份验证切换请求

¥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 个)的名称和可能的初始数据。可以使用连接配置选项提供其他密码 - password2password3。同样,对于每个身份验证因素,插件算法可能需要多次往返数据交换。

¥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);
};
},
},
});