如果用户正在使用基本身份验证,是否有可能从网站注销用户?
仅仅杀掉会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,所以用户下一次使用相同的凭据访问站点时会自动登录。
目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。
如果用户正在使用基本身份验证,是否有可能从网站注销用户?
仅仅杀掉会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,所以用户下一次使用相同的凭据访问站点时会自动登录。
目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。
对于bobince的回答的补充...
使用Ajax,您可以将“注销”链接/按钮连接到一个JavaScript函数。使此函数发送带有错误用户名和密码的XMLHttpRequest。这应该会得到一个401的响应。然后将document.location设置回先前的登录页面。这样,用户在注销时将永远不会看到额外的登录对话框,也不必记住输入错误的凭据。
基本认证并不是用来管理登出的。你可以实现,但不能完全自动化。
您需要做的是让用户单击注销链接,并以相应方式发送“401未经授权”的响应,使用与请求登录时发送的普通401相同的领域和在相同的URL文件夹级别上。
他们必须接下来输入错误的凭据,例如空白的用户名和密码,然后返回一个“您已成功退出”的页面。错误/空白的凭据将覆盖先前正确的凭据。
简而言之,登出脚本反转了登录脚本的逻辑,仅在用户 没有通过正确的凭据时返回成功页面。
问题是有多少用户会接受有点奇怪的“不要输入密码”的密码框。尝试自动填充密码的密码管理器也可能会妨碍此处的操作。
编辑以添加对评论的回应:重新登录略有不同的问题(除非您显然需要两步退出/登录)。您必须拒绝(401)第一次尝试访问重新登录链接,然后接受第二个(其中可能有不同的用户名/密码)。有几种方法可以做到这一点。一种方法是在注销链接中包含当前用户名(例如/relogin?username),并在凭据与用户名匹配时拒绝。
document.execCommand("ClearAuthenticationCache")
var p = window.location.protocol + '//'
// current location must return 200 OK for this GET
window.location = window.location.href.replace(p, p + 'logout:password@')
logout
用户名来执行上述操作。例如:(function(safeLocation){
var outcome, u, m = "You should be logged out now.";
// IE has a simple solution for it - API:
try { outcome = document.execCommand("ClearAuthenticationCache") }catch(e){}
// Other browsers need a larger solution - AJAX call with special user name - 'logout'.
if (!outcome) {
// Let's create an xmlhttp object
outcome = (function(x){
if (x) {
// the reason we use "random" value for password is
// that browsers cache requests. changing
// password effectively behaves like cache-busing.
x.open("HEAD", safeLocation || location.href, true, "logout", (new Date()).getTime().toString())
x.send("")
// x.abort()
return 1 // this is **speculative** "We are done."
} else {
return
}
})(window.XMLHttpRequest ? new window.XMLHttpRequest() : ( window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : u ))
}
if (!outcome) {
m = "Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser."
}
alert(m)
// return !!outcome
})(/*if present URI does not return 200 OK for GET, set some other 200 OK location here*/)
您也可以将其制作为书签:
javascript:(function (c) {
var a, b = "You should be logged out now.";
try {
a = document.execCommand("ClearAuthenticationCache")
} catch (d) {
}
a || ((a = window.XMLHttpRequest ? new window.XMLHttpRequest : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : void 0) ? (a.open("HEAD", c || location.href, !0, "logout", (new Date).getTime().toString()), a.send(""), a = 1) : a = void 0);
a || (b = "Your browser is too old or too weird to support log out functionality. Close all windows and restart the browser.");
alert(b)
})(/*pass safeLocation here if you need*/);
<a href='javascript:......need*/);'>Logout</a>
即可。 - Eric以下函数已经确认在Firefox 40,Chrome 44,Opera 31和IE 11上可用。
Bowser用于浏览器检测,也使用了jQuery。
- secUrl是指密码保护区域的网址,用于注销登录。
- redirUrl是指非密码保护区域的网址(注销成功页面)。
- 您可能希望增加重定向计时器的时间(当前为200毫秒)。
function logout(secUrl, redirUrl) {
if (bowser.msie) {
document.execCommand('ClearAuthenticationCache', 'false');
} else if (bowser.gecko) {
$.ajax({
async: false,
url: secUrl,
type: 'GET',
username: 'logout'
});
} else if (bowser.webkit) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", secUrl, true);
xmlhttp.setRequestHeader("Authorization", "Basic logout");
xmlhttp.send();
} else {
alert("Logging out automatically is unsupported for " + bowser.name
+ "\nYou must close the browser to log out.");
}
setTimeout(function () {
window.location.href = redirUrl;
}, 200);
}
$.ajax
变体为什么是同步的(async: false
),而xmlhttp
变体是异步的(open()
中的true
)? - Bowi(bowser.gecko)
更改为(bowser.gecko || bowser.blink)
。 - Bowi$.ajax
,而WebKit使用new XMLHttpRequest
?Gecko/Blink不应该也能够使用XMLHttpRequest
,而WebKit也能够使用$.ajax
吗?我感到困惑。 - RemyNL以下是使用jQuery的非常简单的Javascript示例:
function logout(to_url) {
var out = window.location.href.replace(/:\/\//, '://log:out@');
jQuery.get(out).error(function() {
window.location = to_url;
});
}
这将使用户退出,而不再显示浏览器的登录框,然后将其重定向到一个已注销页面。
使用基本认证直接做到这一点是不可能的。
HTTP规范中没有机制让服务器告诉浏览器停止发送用户已经提交的凭据。
通常情况下,有一些“技巧”(请参见其他答案),涉及使用XMLHttpRequest发送带有错误凭证的HTTP请求来覆盖最初提供的凭证。
仅供记录,现在有一个新的HTTP响应头称为Clear-Site-Data
。如果您的服务器回复包括一个Clear-Site-Data: "cookies"
头,则应删除认证凭据(不仅是cookie)。我在Chrome 77上进行了测试,但这个警告显示在控制台上:
Clear-Site-Data header on 'https://localhost:9443/clear': Cleared data types:
"cookies". Clearing channel IDs and HTTP authentication cache is currently not
supported, as it breaks active network connections.
这些认证凭证并未被移除,因此目前无法实现基本身份验证的注销,但也许将来会有所改善。在其他浏览器上尚未进行测试。
参考资料:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data
https://www.w3.org/TR/clear-site-data/
https://github.com/w3c/webappsec-clear-site-data
https://caniuse.com/#feat=mdn-http_headers_clear-site-data_cookies
Clear-Site-Data: "cookies"
(根据 MDN,这也应该清除身份验证数据)时,控制台会显示 Clear-Site-Data header forced the clean up of “cookies” data
,但是 Authentication
标头仍然存在于后续请求中。 - Robin Métral以下内容可适用于IE/Netscape/Chrome:
function ClearAuthentication(LogOffPage)
{
var IsInternetExplorer = false;
try
{
var agt=navigator.userAgent.toLowerCase();
if (agt.indexOf("msie") != -1) { IsInternetExplorer = true; }
}
catch(e)
{
IsInternetExplorer = false;
};
if (IsInternetExplorer)
{
// Logoff Internet Explorer
document.execCommand("ClearAuthenticationCache");
window.location = LogOffPage;
}
else
{
// Logoff every other browsers
$.ajax({
username: 'unknown',
password: 'WrongPassword',
url: './cgi-bin/PrimoCgi',
type: 'GET',
beforeSend: function(xhr)
{
xhr.setRequestHeader("Authorization", "Basic AAAAAAAAAAAAAAAAAAA=");
},
error: function(err)
{
window.location = LogOffPage;
}
});
}
}
$(document).ready(function ()
{
$('#Btn1').click(function ()
{
// Call Clear Authentication
ClearAuthentication("force_logout.html");
});
});