如何使用BASICauthentication从网站注销用户?
如果他使用基本身份validation,是否可以从网站注销用户?
杀死会话是不够的,因为一旦用户通过validation,每个请求都包含login信息,所以用户下一次使用相同凭证访问站点时会自动login。
到目前为止唯一的解决scheme是closures浏览器,但从可用性的angular度来看这是不可接受的。
基本身份validation不旨在pipe理注销。 你可以做,但不能完全自动。
你必须做的是让用户点击一个注销链接,并发送一个“401未授权”的响应,使用相同的领域,并在相同的URL文件夹级别发送请求login正常401。
必须指示他们接下来input错误的凭证,例如。 一个空白的用户名和密码,作为回应,你发回一个“你已经成功注销”页面。 然后,错误/空白凭据将覆盖以前正确的凭据。
简而言之,注销脚本会颠倒login脚本的逻辑,如果用户未传递正确的凭证,则只返回成功页面。
问题在于是否有些好奇的“不要input密码”密码框会符合用户的接受程度。 尝试自动填充密码的密码pipe理器也可以在这里获得。
编辑添加回应评论:重新login是一个稍微不同的问题(除非你需要明显的两步注销/login)。 您必须拒绝(401)第一次访问重新login链接的尝试,而不是接受第二次(推测具有不同的用户名/密码)。 有几种方法可以做到这一点。 一种方法是在注销链接中包含当前用户名(例如/ relogin?用户名),并在证书与用户名匹配时拒绝。
除了由bobince的答案…
使用Ajax,您可以将“注销”链接/button连接到Javascriptfunction。 有这个函数发送一个错误的用户名和密码XMLHttpRequest。 这应该返回一个401.然后将document.location设置回预login页面。 这样,用户将不会在注销期间看到额外的login对话框,也不必记得input错误的凭据。
让用户点击指向https:// log:out@example.com/的链接 。 这将覆盖现有的凭据与无效的; 注销它们。
你可以完全使用JavaScript:
IE有(很长一段时间)清除基本身份validationcaching的标准API:
document.execCommand("ClearAuthenticationCache")
应该在工作时返回true。 返回false,未定义或在其他浏览器上爆炸。
新的浏览器(截至2012年12月:Chrome,FireFox,Safari)具有“神奇”的行为。 如果他们看到一个成功的基本身份validation请求(使用任何虚假的其他用户名(让我们说logout
)),他们清除凭证caching,并可能设置为新的伪造用户名,你需要确保不是一个有效的用户名查看内容。
基本的例子是:
var p = window.location.protocol + '//' // current location must return 200 OK for this GET window.location = window.location.href.replace(p, p + 'logout:password@')
执行上述操作的“asynchronous”方法是使用logout
用户名执行AJAX调用。 例:
(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*/);
以下function已确认可用于Firefox 40,Chrome 44,Opera 31和IE 11。
Bowser用于浏览器检测,也使用jQuery。
– secUrl是从中注销密码保护区域的url。
– redirUrl是非密码保护区域(注销成功页面)的url。
– 您可能希望增加redirect计时器(目前为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); }
基本身份validation不是直接可能的。
HTTP规范中没有任何机制可以告诉浏览器停止发送用户已经出示的证书。
有“黑客”(见其他答案)通常涉及使用XMLHttpRequest发送一个HTTP请求与不正确的凭据覆盖原来提供的。
这是一个非常简单的使用jQuery的Javascript示例:
function logout(to_url) { var out = window.location.href.replace(/:\/\//, '://log:out@'); jQuery.get(out).error(function() { window.location = to_url; }); }
这个日志用户没有再次显示他的浏览器login框,然后redirect到一个注销的页面
这适用于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"); }); });
这其实很简单。
只需在浏览器中访问以下内容,并使用错误的凭据: http:// username:password@yourdomain.com
这应该“注销”。
function logout(url){ var str = url.replace("http://", "http://" + new Date().getTime() + "@"); var xmlhttp; if (window.XMLHttpRequest) xmlhttp=new XMLHttpRequest(); else xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) location.reload(); } xmlhttp.open("GET",str,true); xmlhttp.setRequestHeader("Authorization","Basic xxxxxxxxxx") xmlhttp.send(); return false; }
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; }
所有你需要的是redirect用户的一些注销URL,并返回401 Unauthorized
错误。 在错误页面上(必须在没有基本身份validation的情况下才能访问),您需要提供到您的主页的完整链接(包括scheme和主机名)。 用户将点击这个链接,浏览器将再次要求凭证。
Nginx的例子:
location /logout { return 401; } error_page 401 /errors/401.html; location /errors { auth_basic off; ssi on; ssi_types text/html; alias /home/user/errors; }
错误页面/home/user/errors/401.html
:
<!DOCTYPE html> <p>You're not authorised. <a href="<!--# echo var="scheme" -->://<!--# echo var="host" -->/">Login</a>.</p>
根据我上面看到的,我得到了一个适用于任何浏览器的简单解决scheme:
1)在你注销页面你调用一个ajax到你的login后端。 您的login后端必须接受注销用户。 一旦后端接受,浏览器清除当前用户并且采取“注销”用户。
$.ajax({ async: false, url: 'http://your_login_backend', type: 'GET', username: 'logout' }); setTimeout(function () { window.location.href = 'http://normal_index'; }, 200);
2)现在,当用户回到正常的索引文件时,它将尝试使用用户“注销”自动进入系统,在这第二次,你必须通过回复401来阻止它,以调用login/密码对话框。
3)有很多方法可以做到这一点,我创build了两个login后端,一个接受注销用户,另一个不接受。 我的正常login页面使用不接受的,我的注销页面使用接受它的那个。
- 使用会话ID(cookie)
- 使服务器上的会话ID无效
- 不要接受使用无效会话ID的用户
此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+'/'; }
添加到您的应用程序:
@app.route('/logout') def logout(): return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})
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); }
我更新了现代Chrome版本的mthoring解决scheme:
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 || bowser.chrome) { var xmlhttp = new XMLHttpRequest(); xmlhttp.open(\"GET\", secUrl, true); xmlhttp.setRequestHeader(\"Authorization\", \"Basic logout\");\ xmlhttp.send(); } else { // http://stackoverflow.com/questions/5957822/how-to-clear-basic-authentication-details-in-chrome redirUrl = url.replace('http://', 'http://' + new Date().getTime() + '@'); } setTimeout(function () { window.location.href = redirUrl; }, 200); }