HTTP 基本身份验证凭据会一直存储到浏览器关闭,但是有没有办法在浏览器关闭之前删除凭据?
我读到了一个 trick with HTTP 401 status code,但它似乎是 work not properly(见评论回答)。也许是 mechanism trac uses is the solution。
可以使用 JavaScript 删除凭据吗?还是结合使用 JavaScript 和状态 401 技巧?
更新:此解决方案在许多浏览器中似乎不再适用。凯苏评论:
这种发送虚假凭据以使浏览器忘记正确的身份验证凭据的解决方案在 Chrome (16) 和 IE (9) 中不起作用。适用于 Firefox (9)。
实际上,您可以通过向服务发送虚假凭据来实施解决方法。这在浏览器中通过发送另一个(不存在的?)没有密码的用户名来工作。浏览器会丢失有关经过身份验证的凭据的信息。
例子:
https://www.example.com/ => 以“user1”身份使用基本身份验证现在打开 https://foobar@www.example.com/ 您已注销。 ;)
问候
Ps:但是在依赖给定信息之前,请使用所有需要的浏览器进行测试。
扩展 Jan. 的答案,并更新 owyongsk 的答案:
这是一些示例 jquery java-script 代码,可导致浏览器实质上向您尝试保护的页面发送虚假登录请求,这在所有经过测试的浏览器中都会导致缓存的凭据被删除,然后将用户重定向到未受保护的页。
出现问题时的 alert() 可能应该更改为其他内容。
//Submits an invalid authentication header, causing the user to be 'logged out'
function logout() {
$.ajax({
type: "GET",
url: "PUT_YOUR_PROTECTED_URL_HERE",
dataType: 'json',
async: true,
username: "some_username_that_doesn't_exist",
password: "any_stupid_password",
data: '{ "comment" }'
})
//In our case, we WANT to get access denied, so a success would be a failure.
.done(function(){
alert('Error!')
})
//Likewise, a failure *usually* means we succeeded.
//set window.location to redirect the user to wherever you want them to go
.fail(function(){
window.location = "/";
});
}
然后它就像让注销链接调用 logout() 函数一样简单,并且它似乎对用户无缝工作,尽管它在技术上仍然是一个黑客工作。
您可以尝试目前正在使用最新的 Chrome 和 Firefox 的 hack。在您的服务器上创建一个“/logout”页面,该页面只接受特定的凭据,例如用户名:false,密码:false。然后使用下面的这个 AJAX 请求,您可以将用户发送到该页面。
$("#logout").click(function(e){
e.preventDefault();
var request = new XMLHttpRequest();
request.open("get", "/logout", false, "false", "false");
request.send();
window.location.replace("WHEREVER YOU WANT YOUR LOGGED OUT USER TO GO");
});
发生的情况是,假的用户名和密码是从有效的 XMLHttpRequest 而不是当前用户的凭据中缓存的,当用户尝试登录任何页面时,它将使用缓存的假凭据,身份验证失败,它会询问用户进入另一个。希望这可以帮助!
刚刚完成了一个对我来说很好的实现:在服务器上我评估会话、用户名和密码,所以我跟踪这些信息,登录算法如下:
1.检查用户和密码是否为空,否则返回401。
2.检查我们是否在登录用户列表中注册了会话,如果没有,则检查用户和密码是否有效,如果是,则将会话ID保存在我们的列表中,然后返回401。我将解释这一步:如果会话 ID 是不同的三件事之一: a) 用户正在打开另一个窗口。 b) 用户会话结束,即用户退出。 c) 会话由于不活动而过期。但是,只要用户凭据有效,我们就希望保存会话,但返回 401 要求输入一次密码,如果我们不保存会话,那么用户将永远无法登录,因为我们没有新的会话 ID在我们的列表中。
3.检查用户凭据是否正确,如果正确,则保存会话信息并继续提供页面,否则返回 401。
因此,我唯一需要注销用户的就是在用户请求注销页面并且 Web 浏览器再次显示登录对话框时关闭服务器上的会话。
我在写这篇文章时在想,必须有一个步骤,程序检查用户是否已经登录以避免模仿,也许我可以为每个用户保存多个会话 ID 以允许多个会话,嗯,我想你对它的评论。
希望您能明白这一点,如果您发现任何安全漏洞,请发表评论;)
您可以使用 JavaScript 删除凭据:
$("#logout").click(function(){
try {
document.execCommand("ClearAuthenticationCache");
window.location.href('/logout.html'); // page with logout message somewhere in not protected directory
} catch (exception) {}
});
此代码仅适用于 IE。这就是为什么在此处添加 try/catch 块的原因。此外,出于同样的原因,您应该只为 IE 用户显示注销链接:
<!--[if IE]>
<div id="logout">[Logout]</div>
<![endif]-->
对于其他用户,我的建议是:
<div id="logout2" onclick="alert('Please close your browser window to logout')">[Logout]</div>
如果您可以控制服务器代码,则可以创建一个“注销”功能,该功能会回复“401 Unauthorized”,而不管给定的凭据如何。此故障会强制浏览器删除已保存的凭据。
我刚刚使用 Chrome 34、IE 11、Firefox 25 进行了测试——使用 Express.js 服务器和 HTTP 基本身份验证。
在 Chrome(版本 66)中对我有用的是向返回 401 的 URL 发送 Ajax 请求。这样基本身份验证缓存似乎被清除了。
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "/url_that_returns_401", true);
xhttp.send();
这些代码在 Chrome(版本 83)中对我有用:
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "/url_that_return_401", true);
xhttp.setRequestHeader('Authorization', 'Basic ');
xhttp.send();
需要执行此代码(可能通过按钮单击或控制台窗口)然后出现提示,您需要按取消按钮。然后身份验证字段清除,您可以刷新页面并使用另一个凭据登录。
将 nonce 标记为无效。我对服务器端进行了 Ajax 调用,要求注销。服务器端在标头中获取“Authenticate: Digest...”请求。它从该行中提取 nonce="" 并将其添加到禁用的 nonce 列表中。因此,下次浏览器发送带有“Authenticate: Digest...”行的请求时,服务器会回复 401。这会使浏览器向用户询问新的用户 ID/密码。
适用于我的应用程序,但仅适用于 Digest 身份验证。