使用HTTP基本身份验证时将用户注销

Kei*_*ith 23 basic-authentication logout www-authenticate

我希望用户能够通过HTTP基本身份验证模式登录.

问题是我还希望他们能够再次注销 - 奇怪的是,浏览器似乎并不支持.

这被认为是一种社交黑客风险 - 用户将其机器解锁并且浏览器打开,而其他人可以轻松地访问该网站.请注意,仅关闭浏览器选项卡不足以重置令牌,因此用户可能很容易错过.

所以我想出了一个解决方法,但这是一个完全的问题:

1)将它们重定向到Logoff页面

2)在该页面上激活一个脚本到ajax加载另一个带有伪凭证的页面:

$j.ajax({
    url: '<%:Url.Action("LogOff401", new { id = random })%>',
    type: 'POST',
    username: '<%:random%>',
    password: '<%:random%>',
    success: function () { alert('logged off'); }
});
Run Code Online (Sandbox Code Playgroud)

3)应该总是第一次返回401(强制传递新凭据),然后只接受伪凭证:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOff401(string id)
{
    // if we've been passed HTTP authorisation
    string httpAuth = this.Request.Headers["Authorization"];
    if (!string.IsNullOrEmpty(httpAuth) &&
        httpAuth.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
    {
        // build the string we expect - don't allow regular users to pass
        byte[] enc = Encoding.UTF8.GetBytes(id + ':' + id);
        string expected = "basic " + Convert.ToBase64String(enc);

        if (string.Equals(httpAuth, expected, StringComparison.OrdinalIgnoreCase))
        {
            return Content("You are logged out.");
        }
    }

    // return a request for an HTTP basic auth token, this will cause XmlHttp to pass the new header
    this.Response.StatusCode = 401; 
    this.Response.StatusDescription = "Unauthorized";
    this.Response.AppendHeader("WWW-Authenticate", "basic realm=\"My Realm\""); 

    return Content("Force AJAX component to sent header");
}
Run Code Online (Sandbox Code Playgroud)

4)现在,浏览器接受并缓存随机字符串凭证.当他们访问另一个页面时,它会尝试使用它们,失败,然后提示输入正确的页面.

请注意,我的代码示例使用的是jQuery和ASP.Net MVC,但任何技术堆栈都应该可以实现相同的功能.

在IE6及以上版本中还有另一种方法:

document.execCommand("ClearAuthenticationCache");
Run Code Online (Sandbox Code Playgroud)

但是,这会清除所有身份验证 - 他们会退出我的网站,并且他们也会从电子邮件中退出.所以那就是了.

有没有更好的方法来做到这一点?

我已经看到了其他 问题,但他们已经2岁了 - IE9,FX4,Chrome等现在还有更好的方法吗?

如果没有更好的方法可以做到这一点,可以依靠这个淤泥吗?有没有办法让它更健壮?

rpy*_*rpy 5

简而言之:
鉴于当前基本身份验证的实现,没有可靠的过程可以使用 HTTP 基本或摘要式身份验证实现“注销”。

此类身份验证的工作原理是让客户端向请求添加授权标头。
如果对于某个资源,服务器对所提供的凭据不满意(例如,如果没有),它将以“401 Unauthorized”状态代码进行响应并请求身份验证。为此,它将提供带有响应的WWW-Authenticate标头。

客户端无需等待服务器请求身份验证。它可能只是基于一些本地假设(例如来自上次成功尝试的缓存信息)提供授权标头。

虽然您概述的“清除”身份验证信息的方法很有可能与广泛的客户端(即广泛的浏览器)一起工作,但绝对不能保证另一个客户端可能会“更聪明”并简单地区分正确的身份验证数据您的“注销”页面和目标网站的任何其他页面。

您将认识到使用基于客户端证书的身份验证时存在类似的“问题”。只要没有客户的明确支持,你就可能会陷入失地。

因此,如果“注销”是一个问题,请转向任何基于会话的身份验证。

如果您有权在服务器端实现身份验证,则您可能能够根据应用程序级代码的请求实现一项功能,该功能将忽略授权标头中提供的身份验证信息(如果仍然与当前“会话期间提供的内容相同)” (或者提供一些“超时”,之后将重新请求任何凭据),以便客户端将要求用户提供“新”凭据(执行新登录)。