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

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

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


当前回答

发送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基本身份验证弹出框中保存凭据,即使选择了“记住密码”。其他浏览器可以正确地做到这一点。

其他回答

这在基本身份验证中是不可能直接实现的。

在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>

对于使用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秒多,我继续登录过程,但这次使用的是新的凭据!

发送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基本身份验证弹出框中保存凭据,即使选择了“记住密码”。其他浏览器可以正确地做到这一点。

让用户点击指向https://log:out@example.com/的链接。这将用无效的凭证覆盖现有的凭证;注销它们。

这是通过在URL中发送新的凭证来实现的。在本例中,user="log" password="out"。