在尝试统一认证流程时,遇到了一个问题:如何抑制基本的HTTP认证对话框,并显示自定义的UI界面,以实现跨浏览器的一致用户体验。例如,在Chrome、Firefox或Opera浏览器中输入错误的用户凭据时,用户体验会与Internet Explorer和Safari不同。IE或Safari在几次尝试认证用户失败后会取消请求,而Web应用程序可以显示类似“无法访问账户”的页面。Chrome、Firefox和Opera则会无限期地保持请求(请求将处于挂起状态),直到用户放弃并按下取消按钮。另一个问题是在基本认证的情况下如何注销。
实验围绕Apache服务器的配置进行,但认为这同样可以轻松地应用于IIS或Nginx。因为一切都围绕着基本的HTTP认证。解决方案通过了IE(10、11)、Chrome 49、Firefox 44、Opera 36的测试。
首先,需要配置HTTP服务器,在例子中是Apache。通常,所有不需要认证的静态内容(如图像、脚本、HTML)都无需认证即可使用。但为了解决方案,需要一个需要认证的图像(例如)。在服务器上创建了一个目录,将一个小图像放在那里,并配置了Apache,以便对资源进行认证。
以下是名为'auth_required'的目录的配置示例:
Alias /auth_required /path/auth_required/
<Location /auth_required>
Options Indexes
Order allow,deny
Allow from all
Include "/your/path/here/an_auth_config.conf"
</Location>
创建了一个免费认证目录,用于自定义认证UI。该目录有一个简单的HTML页面,它不会破坏整个门户的安全性,并呈现一个简单的认证页面。
以下是Apache配置的示例:
# 未受保护的资源
<Directory /path/auth>
AuthType None
</Directory>
Alias /auth /path/auth
<Location /auth>
# 无需认证
AuthType None
#Require all granted
DirectoryIndex auth_test.html
</Location>
服务器端需要做的就这些。主要的技巧是在客户端实现的。
下面,将找到带有内联注释的代码示例。该解决方案适用于Internet Explorer、Chrome、Firefox和Opera,但不幸的是,不适用于Safari。
function doLoad() {
// 当页面加载时调用该方法
// 如果用户之前已认证,则应重定向到主页
var user = $.cookie('loggedas');
if (user && user.length > 0) {
authenticate();
}
}
function doAuthenticate() {
// 用户点击用户凭据表单时调用该方法
var user = $('#useridUIID').val();
var pswd = $('#pswdUIID').val();
// 主要技巧:默认认证窗口将被提示,直到传递任何用户名(即使不正确)到XMLHttpRequest
// 但这不适用于Safari
user = (user && user.length > 0 ? user : '' + Date.now().getTime())
authenticate(user, pswd);
}
function authenticate(user, pswd) {
var warning = $('div.warning');
if (!warning.hasClass('hidden')) {
warning.addClass('hidden');
}
// 需要认证的资源路径
var img = location.protocol + '//' + location.host +