在两个已打开的 X 会话之间切换而不需要重新验证。

需要:快速在用户之间切换。
在系统上有一对等效的用户帐户。
更具体地说,对于给定的一对:
- 两个帐户都是普通的 Unix 帐户,只是碰巧被同一个物理用户(人)使用。 - 同一个人几乎总是同时打开两个图形化的 X 会话,每个用户帐户一个,但只需要在屏幕上看到一个。 - 这些是完全独立的帐户,具有不同的邮件配置、浏览器历史记录、文件和不同级别的安全性。 - 帐户之间没有共享内容,在同一个 X 会话中混合这些帐户没有意义(即使在它们之间进行复制粘贴也没有用)。 - 然而,用户需要在它们之间频繁切换。 - 可以很容易地放置一个调用 `dm-tool switch-to-user` 的按钮,但实际上用户在每次切换时都必须重新进行身份验证,这样会导致生产力下降。 - 需要的是允许在两个图形化的 X 会话之间快速切换(例如,单击面板上的按钮)而无需重新进行身份验证。
系统信息和安全影响(放宽本地安全应该没问题)
- 系统是Xubuntu 16.04 Xenial。 - X个座位,登录、锁定、切换由lightdm默认完成。
我知道在保持其他操作安全的同时放宽用户之间的安全性比通常的锁定和切换方法更复杂。幸运的是,在我们的情况下,如果一些本地安全性丢失了也没关系,因为机器在受控的场所。例如,如果解决这个需求导致某种情况(如挂起+恢复)不再自动锁定会话,对于这对用户甚至系统上的每个用户来说,这可能是可以接受的。
不过,最好让用户能够手动锁定会话。
此外,必须保留远程安全性(例如,对这些帐户的SSH访问不能受到解决此问题的影响)。
先搜索再发帖
方法1:使用lightdm工具,但进行适当调整
基本上,使用dm-tool switch-to-user *用户名*并确保用户的会话不被锁定。
在12.04中有效
在Ubuntu 12.04中,我们禁用了light-locker以防止会话锁定,并在每个用户的桌面上设置了一个运行以下命令的图标:
dbus-send --system --type=method_call --print-reply --dest=org.freedesktop.DisplayManager $XDG_SEAT_PATH org.freedesktop.DisplayManager.Seat.SwitchToUser string:$CALLEDUSERNAME string:somesessionname

这个操作成功了:会话切换到所提及的用户$CALLEDUSERNAME
在16.04版本中失败
在16.04版本中,这是不令人满意的:它切换到一个带有预选$CALLEDUSERNAME的登录界面,但仍然需要进行身份验证。所以,基本上结果与dm-tool switch-to-user *username*相同。我没有完全检查,但可能它只是按照dm-tool引起的代码路径执行。
进一步搜索
Bug #1205384 “Lock can be circumvented by switching to console” : Bugs : lxsession package : Ubuntu中寻找线索,没有具体有效的解决方法。
我已经查看了http://archive.ubuntu.com/ubuntu/pool/main/l/lightdm/lightdm_1.18.1-0ubuntu1.tar.gz上的dm-tool源代码(来自Ubuntu - xenial中lightdm软件包的详细信息链接)。
原则看起来是这样的:
  • dm-tool 可执行文件调用 dbus 向 lightdm 发送消息。
  • lightdmhandle_seat_call() 中接收 dbus 事件,调用 seat_switch_to_user()
  • seat_switch_to_user() 调用 g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat); 注册回调函数 switch_authentication_complete_cb()
  • seat_switch_to_user() 然后调用 session_start(),显然创建一个全新的 X 会话以进行身份验证(关于详细信息不确定,可能运行 session_child_run() 调用 PAM)。
  • switch_authentication_complete_cb() 然后切换到现有会话或创建新会话。

下一步

我们是否可以以某种方式指示 PAM 在这种情况下允许而无需提示,但又不会影响其他情况?理想情况下,PAM 的行为只会在切换用户的情况下发生变化,而不会在登录或解锁的情况下发生变化。也许额外的 X 会话仍然会启动,但不会等待用户输入密码。

方法二:找出VT号码并使用chvt

  • 随时获取与目标用户对应的VT号码(可能是因为在登录时,脚本会读取XDG_SEAT_PATH以获取座位号,然后与Xorg命令行连接,告诉相应的VT号码,并将结果写入常规位置)。
  • 需要切换到用户时,获取VT号码并使用chvt。可能需要一些sudo配置。

  • 优点:更简单,不涉及lightdm、PAM或其他混乱,甚至没有明确依赖于lightdm,因此可能在其他地方工作。

  • 缺点:通过hackish方式找出用户和VT号码之间的连接?

结论,重述问题

  • 对第一种方法(通过dm-tool,PAM调整)有何评论?
  • 对第二种方法(通过chvt)有何评论?

感谢您的关注。


1用户会话中的进程具有XDG_VTNR环境变量,该变量直接指示VT号码,而无需连接到Xorg命令行。然而,这些变量在外部是未知的。用户可以运行一个广告脚本来公布这些变量。切换将使用chvt命令,因此可能需要sudo配置。 - Stéphane Gourichon
1实际上,在共享(例如家庭)计算机中,希望能够快速切换用户而不需要一直输入密码的愿望是很常见的,可以在这里(https://askubuntu.com/questions/466662/how-to-disable-password-prompt-for-switching-users-in-graphical-session)或者这里(http://askubuntu.com/questions/320731/ubuntu-13-04-users-switching-without-password)看到。实际上,这是一个长期的退步,因为在Ubuntu Jaunty版本中是支持的,详见Switch Users without locking screen - Stéphane Gourichon
1个回答

总结:已完成,可用,当前解决方案仅适用于合作的多用户环境,可以改进。

我编写了一个可用的概念验证补丁来处理lightdm的工作。

它在这里做到了我们需要的!

请参阅下面的安装说明。

先决条件

  • 至少有两个用户帐户的系统,并且用户愿意允许在图形会话之间快速切换而无需重新输入密码。
  • 每个用户都可以使用完全使用lightdm的任何桌面环境,包括使用light-locker进行会话锁定。Unity和XFCE应该可以工作。

已在XFCE上进行测试。

如何使用,如何查看更改

在执行更改之前,请尝试以下操作:

  • 让用户A打开一个图形会话
  • 让用户B打开另一个图形会话

现在,您可以从任何两个会话中执行以下操作:

    dm-tool switch-to-user userA

或者

    dm-tool switch-to-user userB

变化的影响

如果没有进行改变,您将看到一个登录提示,需要输入密码。

通过进行改变,您将立即看到切换,无需登录提示。

这里的切换非常快速。比Ubuntu 12.04还要快,并且在某些情况下甚至没有闪烁。

实际应用

为了最大限度地受益,我建议在您的桌面环境中的任何位置创建一个启动器图标(无论它在您特定的桌面环境中被称为什么),当点击时运行以下命令:

    dm-tool switch-to-user name-of-other-user

安全警告

应用以下命令将替换系统的lightdm软件包为修改版本,允许在图形会话中切换当前登录的任意两个用户。这会削弱系统安全性,例如用户A以图形方式登录,锁定会话后离开,用户B登录。用户B可以随时解锁用户A的会话并切换到该会话。反之亦然(交换A和B)。

未经管理员访问权限(假设使用sudo,尤其是用于软件包安装),无法应用这些更改。

对我们来说运行良好,但请注意,lightdm是一个重要的软件包,这可能会破坏它或引入其他微妙的错误。破坏它将导致所有用户无法使用图形登录会话。您完全负责使用以下命令的后果。您已经被警告。

永久性警告

更改几乎是永久性的。它们在重新启动后仍然存在。 要恢复更改,请安装(使用aptitudesynaptic或其他工具)常规的lightdm*软件包,这将替换已更改的软件包。

注意,每次Ubuntu更新lightdm软件包并安装更新后,更改将被还原。管理员可以再次应用这些更改。

可能的改进(恢复安全性)

通过巧妙地使用Unix组,可以对这个概念进行改进。只有当前用户和目标用户在任何带有常规文件名的组中列出,例如lightdm-quickswitch-anystringfoolightdm才会允许切换。 这样的修改(可能与其他修改一起)最终可以合并到某个官方解决方案中。

命令

我建议在文本控制台上登录(按下Ctrl-Alt-F1并登录),然后执行下面的步骤。这样可以重新启动lightdm而不会丢失当前的shell。

将以下命令复制粘贴到bash shell中,它将调整lightdm以执行这些更改。

(
set -euxv

echo Making sure system has necessary packages.

echo Installing packages will be done only once but might be long as it may fetch around 40Mbytes of data from the Internet.
sudo apt-get --assume-yes install devscripts

echo Enabling source packages in apt.
sudo sed -i '/^#\sdeb-src /s/^# *//' "/etc/apt/sources.list"
sudo apt-get update
sudo apt-get --assume-yes --no-install-recommends build-dep lightdm

THETEMPDIR=$( mktemp -d )
cd $THETEMPDIR

echo Getting package source

apt-get source lightdm
cd */

pwd

if [ -d .pc ]
then
quilt push -a || echo "Quilt returned an error code, we ignore it because we saw it was sometimes irrelevant."
quilt new allow_switch_between_logged_users_without_authentication
quilt add src/seat.c
fi

patch -p0 <<EOF
--- src/seat.c  2016-07-29 05:19:45.000000000 +0200
+++ src/seat.c  2016-08-15 19:37:11.693364683 +0200
@@ -1578,6 +1578,20 @@

     l_debug (seat, "Switching to user %s", username);

+    if (session)
+    {
+   l_debug (seat, "WIP quick switch: found inactive existing user session, switching to it: %s. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+
+   session_unlock (session);
+   seat_set_active_session (seat, session);
+
+   l_debug (seat, "WIP quick switch to user complete: %s.  For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+   return TRUE;
+    }
+
+    l_debug (seat, "WIP quick switch: no session for user, switching to greeter: %s. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+
+
     /* Attempt to authenticate them */
     session = create_user_session (seat, username, FALSE);
     g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat);
EOF

if [ -d .pc ]
then
quilt refresh
ls -al debian/patches/allow_switch_between_logged_users_without_authentication
cat debian/patches/allow_switch_between_logged_users_without_authentication
fi

echo Building modified packages.

dch -lquickswitch "Allow dm-tool switch-to-user username to switch without authentication if user session is already opened.  WARNING: this negates local security. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating"
head debian/changelog
time dpkg-buildpackage -rfakeroot -uc -b

echo Installing modified packages.

cd ..
PACKAGESTOINSTALL=$( for DEBNAME in *.deb ; do PACKAGENAME="$( echo "$DEBNAME" | cut -f 1 -d _ )" ; if dpkg -l $PACKAGENAME | grep -q ^ii ; then echo $DEBNAME ; fi ; done ) ; sudo dpkg --install ${PACKAGESTOINSTALL}
dpkg -l '*lightdm*'
)

请注意下面的命令将立即关闭所有图形会话,没有保存数据的机会,因此所有用户应该正确关闭应用程序并首先保存所需的数据。

如果软件包安装成功,可以立即激活更改:

    sudo service lightdm restart

或者通过重新启动。

反馈

它对你有用吗?你能想到其他的变体吗? 欢迎提供反馈。


2谢谢 Stéphane,终于又有了两次点击和超快速度的用户切换!对于安全问题来说,“不锁定原会话”而不是“解锁目标会话”,这样用户仍然可以明确地锁定他们的会话,是否更好呢?顺便说一下,在一个新安装的 16.04.1 上运行 shell 脚本之前,需要将源库添加到 sources.list 中。现在如果我也能在切换用户时让我的音乐继续播放就好了... - BlackShift
1@BlackShift 是的,谢谢你的反馈和建议。在测试了那个补丁之后,我也考虑到了“不锁定源会话”,而是“解锁目标会话”。这意味着需要深入研究lightdm代码。阅读Bug #501864 “Regression: fast user switch can no longer be fast ...” : Bugs : Session Menu表明它应该可以根据用户进行配置。一步一步来。再次感谢你。 - Stéphane Gourichon
@BlackShift "在新安装的16.04.1上运行shell脚本之前,需要将源仓库添加到sources.list中" 感谢您的报告。原则上,wget调用和dpkg-source -x应该已经准备好了源代码,而apt-get source只是一个备选方案。如果有其他人再次遇到这个问题,我会尽力进行调查。 - Stéphane Gourichon
一周前,lightdm 1.18.3-0ubuntu1被发布。正如预期的那样,升级后恢复了默认行为。经过确认,上述步骤仍然能够像魔法般快速切换功能。 - Stéphane Gourichon
我已经实施了一个精细化的方案。它允许定义互相信任的用户群组。在保持正常行为的情况下,它可以快速切换到已批准的用户群组。代码相当整洁(在我看来与上游代码一样整洁)。我已经成功地使用了这个解决方案,并愿意分享代码。 - Stéphane Gourichon
刚刚编辑以适应Ubuntu 18.04(同时保持与16.04的兼容性)。 - Stéphane Gourichon
Xubuntu 19.10 切换到了自己的屏幕保护程序 xfce4-screensaver。我曾通过一个 hack(将对 xfce4-screensaver 的调用重定向到 dm-tool switch-to-greeter)来解决当前的问题。如果能找到 lightdm 是如何解锁它的并采取相同的方法,那将更加优雅。 - Stéphane Gourichon
2似乎systemd提供了一些有用的基本功能来实现解决方案。好处是:无需修补lightdm,不会局限于lightdm,也可以与Gnome、KDE等一起使用。我将看看如何使用loginctl lock-session ; OTHERUSERSESSION=\some_magic_here` ; sudo bash -c "loginctl activate $OTHERUSERSESSION ; loginctl unlock-session $OTHERUSERSESSION"`构建一些东西。 - Stéphane Gourichon
1如果会话没有锁定,这个命令可以正常工作:loginctl activate $(loginctl | grep seat0 | grep " c" | grep -v $USER | awk '{print $1}' | head -n 1)。在grep中使用" c"来避免跳过tty会话。 - BlackShift