概述
不知从哪天起,大家都不用Mysql转而使用MariaDB了。
众所周知(其实可能很多人不知道)MariaDB支持插件认证。在MariaDB中新建用户,常见的语句是:
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
这样创建的用户,登录时的认证方式是密码。其实创建用户的语句还可以是:
CREATE USER 'username'@'host' IDENTIFIED VIA 'pluginname' USING 'authstring';
这样创建的用户,登录时的认证方式由插件决定。
本文展示了编写一个简单的MariaDB认证插件的全过程。实现的认证机制是用户输入正确的姓名学号即可登录。显然这一认证机制毫无安全性可言,本文重点在于展示插件编写过程。
本文内容基于MariaDB-10.1.8,操作系统是Ubuntu12.04。假设已经安装好了数据库。
基本原理
一个认证插件分为两部分,服务器侧和客户端侧,两者配合,才能完成整个认证过程。最常见的认证情景是服务器侧提问,客户端侧回答。
MariaDB提供了一个通用的客户端侧“dialog”,该客户端侧的功能是接收服务器侧的问题,将问题显示在终端上,并在终端上读取待登录用户的回答,之后将回答发送给服务器侧。它支持不限个数的问答,还支持普通问题和密码问题两种问题,普通问题在待登录用户输入回答时是有回显的,密码问题在待登录用户输入回答时是没有回显的。由于最后一个问题需要特殊处理,所以实际上有四种类型的问题。问题字符串的第一个字节是问题类型,宏定义如下:
/* mysql/auth_dialog_client.h */
#define ORDINARY_QUESTION "\2"
#define LAST_QUESTION "\3"
#define PASSWORD_QUESTION "\4"
#define LAST_PASSWORD "\5"
由于我们想要编写一个简单的认证插件,所以简单起见,客户端侧就使用“dialog”,完全满足要求。这样,我们便只用编写服务器侧部分。
服务器侧部分要做的事情便是与客户端侧的“dialog”通讯,读取输入的姓名学号进行验证。具体实现见下节。
编写代码
套路部分
认证插件的套路如下:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <mysql/plugin_auth.h>
#include <mysql/auth_dialog_client.h>
static int school_number_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
{
/* 该函数是实际上进行认证的地方,
认证通过返回CR_OK,
认证失败返回CR_ERROR; */
}
static struct st_mysql_auth my_auth_plugin=