现在新购买默认搭载Windows系统的电脑一般都会提供一个Windows Hello身份认证方案,例如指纹或者人脸识别。Howdy是一个在Linux上模仿Windows Hello的程序,可以实现在系统用户登录锁屏登录sudo su等身份认证时候使用人脸识别。

安装及调试

Howdy开源地址:https://github.com/boltgolt/howdy

Howdy程序本身的使用方法官方已经已经非常详细了,在此仅做补充。

除了说明提到的Ubuntu or Linux MintDebianArch LinuxFedoraopenSUSE这些Linux发行版之外,基于这些系统的一系列发行版系统都是可以用的。例如Raspberry Pi OSKali

支持Windows Hello的笔记本电脑配有红外摄像头和红外光线发射器。红外网络摄像头通常可以在Linux上自动检测到,但默认情况下,红外光线发射器不起作用。为了使它们工作,请安装和配置linux-enable-ir-emitter

配置中官方有启用说明:

How to enable your infrared emitter ?

  1. linux-enable-ir-emitter -h (each sub-command also has a help -h)
  2. sudo linux-enable-ir-emitter configure look at the ir emitter and answer to the asked questions. You can specify your infrared camera with the option -d /dev/videoX, by default is /dev/video2.
  3. reboot

补充一些调试细节:

你的红外摄像头可能是/dev/video0,但是红外发射器+摄像头可能是/dev/video1。换句话说,这两个地址都可以调用摄像头,但是可能只有后者可以在调用摄像头的同时启动红外发射器。

配置完成后可以通过linux-enable-ir-emitter test查看红外发射器是否可以正常工作,可以正常工作后可以通过linux-enable-ir-emitter boot设置开机启动。

配置完红外功能后,再执行howdy test可以实时查看摄像头,拉上窗帘关闭灯看是否还能看清自己的脸。

通过/lib/security/howdy/config.ini配置文件里面的dark_threshold参数可以调节黑暗阈值,由于红外发射器是闪烁的,某些频率摄像头可能完全看不到物体,可以通过测试不同的值获得更好的黑暗环境下识别的效果。

常见问题

Q: 我可以跳过”登录”按钮吗?

A: 不可以。由于危险的行为和对调用sudo的担忧#170,在5.2.1+版本中删除了dismiss_lockscreen配置项。

Q: 每次登录桌面都要输入用户名,是否可以设置默认登录用户?

A: 严格来说这与howdy无关,而是与对应Linux发行版的Desktop程序有关系。常见的LightDM支持通过设置解决该问题。详见后文。

Q: 提示登录密钥环没有被解锁。(The login keyring did no get unlocked)

A: “我想说这不是一个问题,而是预期的。默认情况下,密钥环会使用您的密码 解密。 这是保证他们的存储安全的唯一方法。但是,一旦您登录,密钥环就会一直解密,因此我认为面部识别是一种快速再次登录的方式,而不是让您登录的主要方式。无论如何,这非常不安全。”——#39

LightDM设置默认登录用户名

执行lightdm --show-config可以看到当前LigntDM配置信息。

$ lightdm --show-config  
   [Seat:*]
B  greeter-session=lightdm-greeter
B  greeter-hide-users=true
B  session-wrapper=/etc/X11/Xsession

Sources:
B  /usr/share/lightdm/lightdm.conf.d/01_debian.conf
B  /usr/share/lightdm/lightdm.conf.d/01_debian.conf
C  /etc/lightdm/lightdm.conf

可以看到配置文件B中配置了greeter-hide-users=true,我们只需要修改/usr/share/lightdm/lightdm.conf.d/01_debian.conf文件设置greeter-hide-users=false即可展示可选的登录用户信息,默认选中上一次登录的用户。如果配置文件B没有此配置项,那么可以直接在/etc/lightdm/lightdm.conf中添加该配置。

LightDM 中的default-user配置选项早已在多年前被废弃。如果您的计算机被多人使用,那么默认选中的用户将会是最后一次登录的用户,因此,如果您希望固定默认选中的用户名,可以使用脚本动态修改/var/lib/lightdm/.cache/lightdm-gtk-greeter/state文件来实现固定默认用户的功能。

  1. 创建/usr/local/bin/lightdm-default-user脚本(脚本来自此处):#!/bin/sh # LightDM removed the default-user option.# The only recourse now is an ugly kludge.# Note that if you want to default to the "Guest Session",# you need to specify the last user as "*guest". /bin/echo -e '[greeter]nlast-user=*guest' > /var/lib/lightdm/.cache/lightdm-gtk-greeter/state
  2. 修改上诉脚本文件中的*guest为您的默认用户的用户名。
  3. 执行chmod 755 /usr/local/bin/lightdm-default-user赋予该脚本可执行权限。
  4. 编辑/etc/lightdm/lightdm.conf文件,添加下述内容,让lightdm在启动时自动运行该脚本:[SeatDefaults] greeter-setup-script=/usr/local/bin/lightdm-default-user

正如原作者所说,这个方法比较丑陋,但却是目前最完美的解决方案。

添加对Python3的支持

本文发布时使用的是 Hodwdy2.6.1版本,然而随着各个Linux发行版逐步移除对 python2 的支持,导致howdy在升级了Linux系统后可能出现异常。

查看无法人脸识别的报错信息:

cat /var/log/auth.log

提示如下报错:

Oct 27 23:24:26 [localhost] sudo:     yige : TTY=pts/0 ; PWD=/home/yige/Downloads ; USER=root ; COMMAND=/usr/bin/apt remove nodejs
Oct 27 23:24:26 [localhost] /lib/security/howdy/pam.py[11808]: Traceback (most recent call last):
Oct 27 23:24:26 [localhost] /lib/security/howdy/pam.py[11808]:   File "/lib/security/howdy/pam.py", line 10, in <module>
Oct 27 23:24:26 [localhost] /lib/security/howdy/pam.py[11808]:     import ConfigParser
Oct 27 23:24:26 [localhost] /lib/security/howdy/pam.py[11808]: ModuleNotFoundError: No module named 'ConfigParser'

可见No module named 'ConfigParser'是由于ConfigParser模块出现异常。

Python3中,ConfigParser已经更名为configparser

目前howdy作者还没有发布新版本添加对python3的支持,因此可以通过手工修改/lib/security/howdy/pam.py文件实现兼容:

# PAM interface in python, launches compare.py# Import required modules
import subprocess
import os
import glob
import sys
import syslog

# pam-python is running python 2, so we use the old module here
if sys.version_info.major < 3:
    import ConfigParser
    config = ConfigParser.ConfigParser()
else:
    import configparser
    config = configparser.ConfigParser()

# Read config from disk
config.read(os.path.dirname(os.path.abspath(__file__)) + "/config.ini")

...

将此文件前面几行修改如上即可。重启后howdy即可正常运行。