是否有可能注销用户从一个网站,如果他是使用基本身份验证?

杀死会话是不够的,因为一旦用户通过身份验证,每个请求都包含登录信息,因此用户下次使用相同的凭据访问站点时将自动登录。

目前唯一的解决方案是关闭浏览器,但从可用性的角度来看,这是不可接受的。


当前回答

这适用于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"); 
      });
  });          

其他回答

对于使用Windows身份验证(也称为协商、Kerberos或NTLM身份验证)的任何人,我使用ASP。NET Core和Angular。

我找到了一种有效的方式来改变用户!

我修改我的登录方法在javascript方面,就像这样:

protected login(changeUser: boolean = false): Observable<AuthInfo> {
  let params = new HttpParams();
  if(changeUser) {
    let dateNow = this.datePipe.transform(new Date(), 'yyyy-MM-dd HH:mm:ss');
    params = params.set('changeUser', dateNow!);
  }
  const url: string = `${environment.yourAppsApiUrl}/Auth/login`;
  return this.http.get<AuthInfo>(url, { params: params });
}

下面是我在后台的方法:

[Route("api/[controller]")]
[ApiController]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = NegotiateDefaults.AuthenticationScheme)]
public class AuthController : Controller
{
  [HttpGet("login")]
  public async Task<IActionResult> Login(DateTime? changeUser = null)
  {
      if (changeUser > DateTime.Now.AddSeconds(-3))
          return Unauthorized();

      ...
      ... (login process)
      ...

      return Ok(await _authService.GetToken());
    }
}

return Unauthorized()返回401代码,导致浏览器识别弹出窗口出现,以下是过程:

如果我想更改用户,我现在将日期作为参数传输。 如果从那一刻起不超过3秒,我就返回401代码。 我完成了我的凭证,并将具有相同参数的相同请求发送到后端。 由于已经过去了3秒多,我继续登录过程,但这次使用的是新的凭据!

下面是一个使用jQuery的非常简单的Javascript示例:

function logout(to_url) {
    var out = window.location.href.replace(/:\/\//, '://log:out@');

    jQuery.get(out).error(function() {
        window.location = to_url;
    });
}

此登录用户退出而不再次显示浏览器登录框,然后将其重定向到注销页面

添加到你的应用程序:

@app.route('/logout')
def logout():
    return ('Logout', 401, {'WWW-Authenticate': 'Basic realm="Login required"'})

发送https://invalid_login@hostname在任何地方都可以工作,除了Mac上的Safari(好吧,没有勾选Edge,但也应该工作)。

当用户在HTTP基本身份验证弹出框中选择“记住密码”时,Safari中的注销不工作。在这种情况下,密码存储在Keychain Access (Finder > Applications > Utilities > Keychain Access(或CMD+SPACE并键入“Keychain Access”))中。发送https://invalid_login@hostname不会影响钥匙链访问,所以这个复选框不可能在Mac上的Safari上注销。至少它是如何为我工作的。

MacOS Mojave (10.14.6), Safari 12.1.2。

下面的代码在Firefox(73)、Chrome(80)和Safari(12)中运行良好。当用户导航到登出页面时,执行代码并删除凭据。

    //It should return 401, necessary for Safari only
    const logoutUrl = 'https://example.com/logout'; 
    const xmlHttp = new XMLHttpRequest();
    xmlHttp.open('POST', logoutUrl, true, 'logout');
    xmlHttp.send();

此外,由于某些原因,Safari不会在HTTP基本身份验证弹出框中保存凭据,即使选择了“记住密码”。其他浏览器可以正确地做到这一点。

此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+'/';
}