使用IIS7和一个插件的WordPress自动登录


对于我们的 RealDolmen博客平台 ,我们使用 Wordpress 作为运行多个外部和内部博客的引擎(是的,那是我们的内部SaaS!),我们希望有一个简单的解决方案让我们的员工登录到平台。我们看了一下Wordpress的插件库,发现了优秀的 Simple LDAP Login 插件,通过活动目录提供登录。这允许使用活动目录凭证进行登录。然而,当从公司网络浏览博客时,登录页面是用户的一个额外步骤:他们已经登录到网络上了,为什么还要使用相同的凭证再次登录?

幸运的是,我们在 Windows、IIS 7和SQL Server 上托管 Wordpress 。 震惊吗?那里没有Linux、MySQL、.htaccess和mod_rewrite! 而且它工作得非常好。事实上,我们免费得到了一些额外的东西:单点登录是由IIS实现的!

在IIS7中配置Windows认证

为了在IIS上为Wordpress提供一个单点登录方案,只需在IIS7管理控制台中启用Windows认证,像这样。

Windows Authentication in IIS - Wordpress, PHP

如果你现在浏览Wordpress网站......什么也不会发生!除了正常的东西:一个非登录的网站。原因很明显:匿名认证也被启用了,而且是在链的上游,因此IIS7拒绝使用用户的活动目录凭证来认证用户......一个解决方案可能是颠倒顺序,但这将意味着*每个用户都需要登录。这就是我们为Wordpress定制的插件的用武之地,嘿嘿,我们甚至与你分享它,你也可以使用它

在需要时愚弄IIS7......

在IIS7中,匿名认证的地位较高,而这是我们不希望每个人都必须登录的事实所要求的,解决这个问题的办法是愚弄IIS7,使其相信在某些情况下Windows认证的地位较高......为什么不从PHP做起,把这个 "黑 "包进Wordpress插件呢?

我们的插件的基础是:只要用户浏览网站并使用Internet Explorer(对不起,其他浏览器不支持这个......),Windows认证就是一种可能。剩下的唯一步骤是触发这个,这很容易:如果你检测到一个用户来自本地局域网,并且使用Internet Explorer(在Windows上),向用户发送一个 HTTP/1.1 401 Unauthorized 头。 这将使IE向服务器发送Windows认证令牌,也会欺骗IIS7认为匿名认证失败,这也会立即触发Windows认证的服务器端。

现在,如何在Wordpress插件中做到这一点?嗯,很简单:钩住Wordpress提供的两个事件,即 init login_form 。启动?嗯,是的! 你想让用户在从局域网来时自动登录。没有比 init 更好的钩子了。 另一个是显而易见的:如果用户以某种方式进入登录页面,并且来自本地局域网,你希望跳过该页面,在那里使用Windows认证。下面是一些注册钩子的简化代码。

1<?php
2add_action('init','iisauth_auto_login');
3add_action('login_form','iisauth_wp_login_form');

下一步,实施! 让我们从 init 上发生的事情开始:

1function iisauth_auto_login() {
2if (!is_user_logged_in() && iisauth_is_lan_user() && iisauth_using_ie()) {
3        iisauth_wp_login_form();
4    }
5}

正如你所看到的:每当我们怀疑一个用户来自内部局域网并使用IE时,我们就调用 iisauth_wp_login_form() 方法(当用户在登录页面时,它也 "意外地 "被触发)。下面是那段代码。

 1function iisauth_wp_login_form() {
 2// Checks if IIS provided a user, and if not, rejects the request with 401
 3    // so that it can be authenticated
 4if (iisauth_is_lan_user() && iisauth_using_ie() &&empty($_SERVER["REMOTE_USER"])) {
 5        nocache_headers();
 6header("HTTP/1.1 401 Unauthorized");
 7ob_clean();
 8exit();
 9    } elseif (iisauth_is_lan_user() && iisauth_using_ie() &&!empty($_SERVER["REMOTE_USER"])) {
10if (function_exists('get_userdatabylogin')) {
11$username=strtolower(substr($_SERVER['REMOTE_USER'],strrpos($_SERVER['REMOTE_USER'],'\\') +1));
12
13$user= get_userdatabylogin($username);
14if (!is_a($user,'WP_User')) {
15// Create the user
16$newUserId= iisauth_create_wp_user($username);
17if (!is_a($newUserId,'WP_Error')) {
18$user= get_userdatabylogin($username);
19                }
20            }
21
22if ($user&&$username==$user->user_login) {
23// Clean buffers
24ob_clean();
25
26// Feed WordPress a double-MD5 hash (MD5 of value generated in check_passwords)
27$password=md5($user->user_pass);
28
29// User is now authorized; force WordPress to use the generated password
30$using_cookie=true;
31                wp_setcookie($user->user_login,$password,$using_cookie);
32
33// Redirect and stop execution
34$redirectUrl= home_url();
35if (isset($_GET['redirect_to'])) {
36$redirectUrl=$_GET['redirect_to'];
37                }
38                wp_redirect($redirectUrl);
39exit;
40            }
41        }
42    }
43}

这里发生的事情是,认证头在需要时被发送,一旦IIS提供了一个用户,我们就把用户登录到Wordpress并重定向他。真正的 "魔法 "在这一部分。

1// Checks if IIS provided a user, and if not, rejects the request with 401
2// so that it can be authenticated
3if (iisauth_is_lan_user() && iisauth_using_ie() &&empty($_SERVER["REMOTE_USER"])) {
4    nocache_headers();
5header("HTTP/1.1 401 Unauthorized");
6ob_clean();
7exit();
8}

这正是我之前在这篇文章中所描述的......

下载

好吧,当然,请自由使用这个插件! 这里是源代码。 iisauth.zip (1.44 kb)

(非常感谢我们的市场经理允许我发布这个小插件!)。再次证明了 RealDolmen 的无忧无虑的精神!)