1. 简介
在开启双因子后,用户登录需要输入用户名密码,同时还需要输入 ukey 的 PIN 码才能登录进系统。但是,用户拔出 ukey 时,要做退出登录处理。用户登录可能通过 gonme 桌面登录,也可能通过 tty 终端登录。通过桌面登录后,还可以打开终端。所以做退出登录处理时既要对桌面登录做处理,也要对终端登录做处理。
2. 监听ukey拔出事件
既然要监听 ukey 的拔出事件,就需要要启动一个线程监听 ukey 拔出事件,这是通过监听 gudevclient 模块的uevent 信号实现的,在信号处理函数中判断是否是 ukey 拔出事件。判断 ukey 拔出事件的首要条件是: udev 检测到了一个 block 设备,并且 action 是 remove ,这只能判断出有存储设备拔出。我们用的 ukey 其实就是一个 usb 存储设备。因为 ukey 拔出了,我们无法判断是哪个用户的 ukey 拔出了,有可能只是一个普通的 usb 存储设备被拔出了。所以一旦有 usb 存储设备拔出,要遍历用户与 ukey 的绑定关系存储的目录,查出是否有被绑定的 ukey 拔出了,如果有就查看桌面登录信息和终端登录信息,并进行处理。
对于桌面登录的用户,检测到 ukey 拔出事件后锁定屏幕;而对于终端登录的用户,则将终端退出。
监听 ukey 拔出流程如下图所示:
3. 处理桌面登录用户
对于桌面登录的用户,处理方式比较简单,只需要通过 DBus 总线,调用 org.gnome.ScreenSaver 总线的 org.gnome.ScreenSaver 接口下的 Lock 方法。需要注意的是 org.gnome.ScreenSaver 总线类型是 Session ,所以必须对于每个通过桌面登录的用户都启动一个 ueventmonitor 服务,我们称为 gnome-ueventmonitor 。 gnome-ueventmonitor 随着桌面登录成功而启动,当收到 ukey 拔出事件后,判断当前登录用户是否绑定了 ukey ,如果没绑定,直接发送锁屏指令,如果绑定了,要判断绑定的 ukey 是否出于插入状态,如果 ukey 没有插入则发送锁屏指令。
处理桌面登录用户流程如下图所示:
4. 处理终端登录用户
对于终端登录的用户,处理方式稍微复杂一些。处理终端登录用户 ukey 拔出事件的进程是 ueventmonitor ,该进程是以 root 权限运行的系统服务,当监听到有 ukey 拔出后,首先读取 /var/run/utmp 文件,将数据保存到 utmp 结构体数组中。 /var/run/utmp 文件中保存当前正在本系统中的用户信息, utmp 结构体保存了用户名和对应的终端。你可以通过 w 命令查看当前登录的用户名以及对应的终端名。对于 tty 登录的终端名类型为 pts/n , n 从 0 开始;对于桌面登录的终端名类型为 n , n 从 0 开始。然后,遍历存储用户与 ukey 的绑定关系目录,判断每一个绑定过的 ukey 是否出于插入的状态,如果 ukey 处于拔出状态,接着遍历utmp结构体数组,找出拔出的这个 ukey 对应的用户与 utmp 结构中的 ut_user 字段相等的那个 utmp ,最后调用 fuser –f /dev/pts/n 命令杀死终端,其中 pts/n 就是在 utmp 结构里的 ut_line 字段。
处理终端登录用户流程如下图所示: