我想要一个自定义登录表单来对 Web 服务器进行身份验证。服务器非常简单(它基于嵌入式平台),所以我不能使用复杂的机制(php、asp、ssl、...)。对于我的需要,基本的 HTTP 身份验证很好。此外,我需要注销功能。
我实现了 login.html、/pages/protected.html 和 auth.js。第一个是带有登录表单的索引页面。提交按钮调用 auth.js 中的 login() 函数。第二个是受保护的页面(/pages 文件夹下的所有文件都受到保护),只有正确登录才能看到。在这个页面中有一个注销按钮,它调用 auth.js 中的 logout() 函数。
这是 auth.js 的内容:
var loginURL = "/login.html";
var logoutURL = "/pages/logout.html";
var userAgent = navigator.userAgent.toLowerCase();
function getHTTPObject() {
var xmlhttp = false;
if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else { // code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlhttp;
}
function login(strUrl) {
var user = document.getElementById("txt_username").value;
var pass = document.getElementById("txt_password").value;
var http = getHTTPObject();
http.open("get", strUrl, false, user, pass);
http.send("");
if (http.status == 200) {
document.location = strUrl;
} else {
alert("Incorrect username and/or password!");
}
return false;
}
function logout() {
if (userAgent.indexOf("msie") != -1) {
document.execCommand("ClearAuthenticationCache", false);
}
var http = getHTTPObject();
var logout_url = "/login.html";
http.open("get", logout_url, false);
http.send("");
document.location = logout_url;
return false;
}
如果请求没有 Authorization 标头,则服务器被编程为使用 401 和 WWW-Authenticate HTTP 标头进行响应。如果请求包含带有错误凭据的授权标头,它会回答 403。通过这种方式,我可以避免使用错误凭据的浏览器登录窗口。
使用最新的 Firefox 版本,这非常有效,它也适用于 IE。但有时 IE 坚持弹出带有用户/密码文本框的小对话框窗口,即使在表单中输入的凭据已更正。
我开始以下循环:
- 输入正确的用户名和密码
- 单击登录并出现受保护的页面
- 点击注销
- 转到步骤 1。
在 n 次(n 可以是 1、5 或 10)之后,单击登录按钮后,我会收到来自 IE 的身份验证表单。
如您所知,在清除 IE 中的凭据缓存(使用 ClearAuthenticationCache)后,浏览器首先发送没有凭据的请求(即使 XMLHttpRequest 对象具有用户名和密码参数)。只有当 Web 服务器使用 401 代码和 WWW-Authenticate 标头进行响应时,浏览器才会再次发送带有凭据的请求。
我尝试在普通 PC 上使用 lighttpd 服务器实现相同的页面。在这种情况下,似乎 IE 没有弹出问题。所以IE不太喜欢我的嵌入式服务器(也就是HTTP1.0)的答案。我的服务器使用以下 HTTP 标头进行回答:
- HTTP 1.0(200 表示正确的凭据,401 表示无凭据,403 表示错误的凭据)
- 服务器
- WWW-Authenticate(在没有凭据的情况下)
- 连接:关闭
- 内容类型
lighttpd (HTTP 1.1) 的答案有更多标题:
- HTTP 1.1 和代码
- WWW-认证
- 内容类型
- 内容长度
- 日期
- 服务器
你有什么建议吗?