是否有可能注销用户从一个网站,如果他是使用基本身份验证?
杀死会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,因此用户下次使用相同的凭据访问站点时将自动登录。
目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。
是否有可能注销用户从一个网站,如果他是使用基本身份验证?
杀死会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,因此用户下次使用相同的凭据访问站点时将自动登录。
目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。
当前回答
这在基本身份验证中是不可能直接实现的。
在HTTP规范中,服务器没有机制告诉浏览器停止发送用户已经提供的凭据。
有一些“黑客”(参见其他答案)通常涉及使用XMLHttpRequest发送带有错误凭据的HTTP请求,以覆盖最初提供的凭据。
其他回答
我刚刚在Chrome(79)、Firefox(71)和Edge(44)上测试了以下程序,效果良好。它应用上面提到的脚本解决方案。
只需添加一个“注销”链接,点击返回以下html
<div>You have been logged out. Redirecting to home...</div>
<script>
var XHR = new XMLHttpRequest();
XHR.open("GET", "/Home/MyProtectedPage", true, "no user", "no password");
XHR.send();
setTimeout(function () {
window.location.href = "/";
}, 3000);
</script>
此JavaScript必须适用于所有最新版本的浏览器:
//Detect Browser
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
// Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
var isFirefox = typeof InstallTrigger !== 'undefined'; // Firefox 1.0+
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
// At least Safari 3+: "[object HTMLElementConstructor]"
var isChrome = !!window.chrome && !isOpera; // Chrome 1+
var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var Host = window.location.host;
//Clear Basic Realm Authentication
if(isIE){
//IE
document.execCommand("ClearAuthenticationCache");
window.location = '/';
}
else if(isSafari)
{//Safari. but this works mostly on all browser except chrome
(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);
window.location = '/';
// return !!outcome
})(/*if present URI does not return 200 OK for GET, set some other 200 OK location here*/)
}
else{
//Firefox,Chrome
window.location = 'http://log:out@'+Host+'/';
}
基本身份验证不是为管理注销而设计的。你可以这样做,但不是完全自动的。
你所要做的就是让用户点击登出链接,然后发送一个“401未授权”作为响应,使用与你发送的请求登录的正常401相同的域和URL文件夹级别。
接下来,他们必须被引导输入错误的凭证。一个空白的用户名和密码,作为回应,您发回一个“您已成功注销”页面。错误的/空白的凭证将覆盖之前的正确凭证。
简而言之,登出脚本颠倒了登录脚本的逻辑,只有在用户没有传递正确的凭据时才返回成功页面。
问题是这个有点奇怪的“不要输入密码”的密码框是否能让用户接受。试图自动填充密码的密码管理器也会在这里起到阻碍作用。
编辑添加以回应评论:重新登录是一个稍微不同的问题(除非你显然需要两步注销/登录)。您必须拒绝(401)第一次访问重新登录链接的尝试,然后接受第二次(可能有不同的用户名/密码)。有几种方法可以做到这一点。一种方法是在登出链接中包含当前用户名。/relogin?username),并在凭据与用户名匹配时拒绝。
function logout() {
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("msie") != -1) {
document.execCommand("ClearAuthenticationCache", false);
}
xhr_objectCarte = null;
if(window.XMLHttpRequest)
xhr_object = new XMLHttpRequest();
else if(window.ActiveXObject)
xhr_object = new ActiveXObject("Microsoft.XMLHTTP");
else
alert ("Your browser doesn't support XMLHTTPREQUEST");
xhr_object.open ('GET', 'http://yourserver.com/rep/index.php', false, 'username', 'password');
xhr_object.send ("");
xhr_object = null;
document.location = 'http://yourserver.com';
return false;
}
这适用于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");
});
});