通过 PHP 进行 HTTP 身份验证注销
注销 HTTP 身份验证受保护文件夹的正确方法是什么?
有一些解决方法可以实现此目的,但它们具有潜在的危险,因为它们可能存在错误或在某些情况/浏览器中不起作用。 这就是为什么我正在寻找正确且干净的解决方案。
What is the correct way to log out of HTTP authentication protected folder?
There are workarounds that can achieve this, but they are potentially dangerous because they can be buggy or don't work in certain situations / browsers. That is why I am looking for correct and clean solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
亩。 不存在正确的方法,甚至不存在跨浏览器一致的方法。
这是来自 HTTP 规范 的问题(第 15.6 节):
另一方面,10.4.2 部分说:
换句话说,您可以再次显示登录框(如@Karsten 说),但是浏览器不必满足您的请求 - 所以不要过度依赖这个(错误的)功能。
Mu. No correct way exists, not even one that's consistent across browsers.
This is a problem that comes from the HTTP specification (section 15.6):
On the other hand, section 10.4.2 says:
In other words, you may be able to show the login box again (as @Karsten says), but the browser doesn't have to honor your request - so don't depend on this (mis)feature too much.
在 Safari 中效果很好的方法。 也适用于 Firefox 和 Opera,但有警告。
这告诉浏览器使用新用户名打开 URL,覆盖以前的用户名。
Method that works nicely in Safari. Also works in Firefox and Opera, but with a warning.
This tells browser to open URL with new username, overriding previous one.
简单的答案是您无法可靠地注销 http 身份验证。
长答案:
Http-auth(与 HTTP 规范的其余部分一样)是无状态的。 因此,“登录”或“注销”并不是一个真正有意义的概念。 更好的查看方法是,对于每个 HTTP 请求(请记住,页面加载通常是多个请求)询问“您是否可以执行您所请求的操作?”。 服务器将每个请求视为新请求,并且与任何先前的请求无关。
浏览器选择记住您在第一个 401 中告诉他们的凭据,并在后续请求中未经用户明确许可的情况下重新发送它们。 这是试图为用户提供他们期望的“登录/注销”模型,但这纯粹是一种拼凑。 浏览器正在模拟这种状态持久性。 Web 服务器完全不知道这一点。
因此,在 http-auth 的上下文中,“注销”纯粹是浏览器提供的模拟,因此超出了服务器的权限。
是的,有一些杂凑。 但它们破坏了 RESTful-ness(如果这对您有价值)并且它们是不可靠的。
如果您绝对需要登录/注销模型来进行站点身份验证,那么最好的选择是跟踪 cookie,并以某种方式(mysql、sqlite、平面文件等)将状态持久性存储在服务器上。 这将需要评估所有请求,例如使用 PHP。
The simple answer is that you can't reliably log out of http-authentication.
The long answer:
Http-auth (like the rest of the HTTP spec) is meant to be stateless. So being "logged in" or "logged out" isn't really a concept that makes sense. The better way to see it is to ask, for each HTTP request (and remember a page load is usually multiple requests), "are you allowed to do what you're requesting?". The server sees each request as new and unrelated to any previous requests.
Browsers have chosen to remember the credentials you tell them on the first 401, and re-send them without the user's explicit permission on subsequent requests. This is an attempt at giving the user the "logged in/logged out" model they expect, but it's purely a kludge. It's the browser that's simulating this persistence of state. The web server is completely unaware of it.
So "logging out", in the context of http-auth is purely a simulation provided by the browser, and so outside the authority of the server.
Yes, there are kludges. But they break RESTful-ness (if that's of value to you) and they are unreliable.
If you absolutely require a logged-in/logged-out model for your site authentication, the best bet is a tracking cookie, with the persistence of state stored on the server in some manner (mysql, sqlite, flatfile, etc). This will require all requests to be evaluated, for instance, with PHP.
解决方法
您可以使用 Javascript 执行此操作:
上面所做的是:
对于 IE - 只需清除身份验证缓存并重定向到某处
其他浏览器的某个位置 - 在后台发送带有“注销”登录名和密码的 XMLHttpRequest。 我们需要将其发送到某个路径,该路径将返回 200 OK 到该请求(即它不需要 HTTP 身份验证)。
将
'/where/to/redirect'
替换为注销后重定向到的某个路径,并将'/path/that/will/return/200/OK'
替换为一些您网站上的路径将返回 200 OK。Workaround
You can do this using Javascript:
What is done above is:
for IE - just clear auth cache and redirect somewhere
for other browsers - send an XMLHttpRequest behind the scenes with 'logout' login name and password. We need to send it to some path that will return 200 OK to that request (i.e. it shouldn't require HTTP authentication).
Replace
'/where/to/redirect'
with some path to redirect to after logging out and replace'/path/that/will/return/200/OK'
with some path on your site that will return 200 OK.解决方法(不是一个干净、漂亮(甚至有效!请参阅评论)的解决方案):
禁用他的凭据一次。
您可以通过发送适当的标头(如果未登录)将 HTTP 身份验证逻辑移至 PHP:
并使用以下内容解析输入:
因此,禁用他的凭据一次应该是微不足道的。
Workaround (not a clean, nice (or even working! see comments) solution):
Disable his credentials one time.
You can move your HTTP authentication logic to PHP by sending the appropriate headers (if not logged in):
And parsing the input with:
So disabling his credentials one time should be trivial.
分两步从 HTTP 基本身份验证注销
假设我有一个名为“密码保护”的 HTTP 基本身份验证领域,并且 Bob 已登录。要注销,我发出 2 个 AJAX 请求:
WWW-Authenticate: Basic Realm="Password protected"
此时,浏览器忘记了 Bob 的凭据。
Logout from HTTP Basic Auth in two steps
Let’s say I have a HTTP Basic Auth realm named “Password protected”, and Bob is logged in. To log out I make 2 AJAX requests:
WWW-Authenticate: Basic realm="Password protected"
At this point browser forgot Bob’s credentials.
我对这个问题的解决方案如下。 您可以在本页的第二个示例中找到函数
http_digest_parse
、$realm
和$users
: http://php.net/manual/en/features.http-auth.php。My solution to the problem is the following. You can find the function
http_digest_parse
,$realm
and$users
in the second example of this page: http://php.net/manual/en/features.http-auth.php.我发现清除
PHP_AUTH_DIGEST
或PHP_AUTH_USER
ANDPHP_AUTH_PW
凭据的唯一有效方法是调用标头HTTP/1.1 401 未经授权。
The only effective way I've found to wipe out the
PHP_AUTH_DIGEST
orPHP_AUTH_USER
ANDPHP_AUTH_PW
credentials is to call the headerHTTP/1.1 401 Unauthorized
.通常,一旦浏览器要求用户提供凭据并将其提供给特定网站,它将继续执行此操作而无需进一步提示。 与在客户端清除 cookie 的各种方法不同,我不知道有类似的方法可以要求浏览器忘记其提供的身份验证凭据。
Typically, once a browser has asked the user for credentials and supplied them to a particular web site, it will continue to do so without further prompting. Unlike the various ways you can clear cookies on the client side, I don't know of a similar way to ask the browser to forget its supplied authentication credentials.
Trac - 默认情况下 - 也使用 HTTP 身份验证。 注销不起作用且无法修复:
发件人: http://trac.edgewall.org/ticket/ 791#comment:103
看起来这个问题没有有效的答案,这个问题七年前就已经报道过,而且它非常有道理:HTTP 是无状态的。 请求要么使用身份验证凭据完成,要么不使用身份验证凭据完成。 但这是客户端发送请求的问题,而不是服务器接收请求的问题。 服务器只能判断请求 URI 是否需要授权。
Trac - by default - uses HTTP Authentication as well. Logout does not work and can not be fixed:
From: http://trac.edgewall.org/ticket/791#comment:103
Looks like that there is no working answer to the question, that issue has been reported seven years ago and it makes perfect sense: HTTP is stateless. Either a request is done with authentication credentials or not. But that's a matter of the client sending the request, not the server receiving it. The server can only say if a request URI needs authorization or not.
我需要重置 .htaccess 授权,所以我使用了这个:
在这里找到它:
http://php.net/manual/en/features.http-auth.php
想想吧。
该页面上有许多解决方案,甚至在底部注明:Lynx,不像其他浏览器那样清除身份验证;)
我在我安装的浏览器上测试了它,一旦关闭,每个浏览器似乎始终需要重新身份验证再入。
I needed to reset .htaccess authorization so I used this:
Found it here :
http://php.net/manual/en/features.http-auth.php
Go figure.
A number of solutions reside on that page and it even notes at the bottom: Lynx, doesn't clear the auth like other browsers ;)
I tested it out on my installed browsers and once closed, each browser seems like it consistently requires reauth on reentry.
这可能不是所寻找的解决方案,但我是这样解决的。
我有两个用于注销过程的脚本。
logout.php
log.php
这样我就不会收到警告并且我的会话被终止
This might be not the solution that was looked for but i solved it like this.
i have 2 scripts for the logout process.
logout.php
log.php
This way i dont get a warning and my session is terminated
AFAIK,在使用 htaccess(即基于 HTTP 的)身份验证时,没有干净的方法来实现“注销”功能。
这是因为此类身份验证使用 HTTP 错误代码“401”来告诉浏览器需要凭据,此时浏览器会提示用户输入详细信息。 从那时起,直到浏览器关闭为止,它将始终发送凭据而不会进一步提示。
AFAIK, there's no clean way to implement a "logout" function when using htaccess (i.e. HTTP-based) authentication.
This is because such authentication uses the HTTP error code '401' to tell the browser that credentials are required, at which point the browser prompts the user for the details. From then on, until the browser is closed, it will always send the credentials without further prompting.
到目前为止我发现的最好的解决方案是(它是一种伪代码,
$isLoggedIn
是http身份验证的伪变量):在“注销”时,只需将一些信息存储到会话中即可该用户实际上已注销。
在我检查身份验证的地方,我扩展了条件:
会话在某种程度上与 http 身份验证的状态相关,因此只要用户保持浏览器打开并且只要 http 身份验证在浏览器中持续存在,用户就会保持注销状态。
The best solution I found so far is (it is sort of pseudo-code, the
$isLoggedIn
is pseudo variable for http auth):At the time of "logout" just store some info to the session saying that user is actually logged out.
In the place where I check for authentication I expand the condition:
Session is somewhat linked to the state of http authentication so user stays logged out as long as he keeps the browser open and as long as http authentication persists in the browser.
也许我没有抓住要点。
我发现结束 HTTP 身份验证的最可靠方法是关闭浏览器和所有浏览器窗口。 您可以使用 Javascript 关闭浏览器窗口,但我不认为您可以关闭所有浏览器窗口。
Maybe I'm missing the point.
The most reliable way I've found to end HTTP Authentication is to close the browser and all browser windows. You can close a browser window using Javascript but I don't think you can close all browser windows.
虽然其他人正确地说不可能从基本 http 身份验证注销,但有一些方法可以实现行为类似的身份验证。 一种明显的方法是使用 auth_memcookie。 如果您确实想使用此功能实现基本 HTTP 身份验证(即使用浏览器对话框而不是 HTTP 表单进行登录) - 只需将身份验证设置为单独的 .htaccess 受保护目录,其中包含 PHP 脚本,该脚本重定向回用户之后的位置创建内存缓存会话。
While the others are correct in saying that its impossible to logout from basic http authentication there are ways to implement authentication which behave similarly. One obvious appeoach is to use auth_memcookie. If you really want to implement Basic HTTP authentication (i.e. use the browser dialogs for logging in trather than an HTTP form) using this - just set the authentication to a seperate .htaccess protected directory containing a PHP script which redirects back where te user came after createing the memcache session.
这里有很多伟大而复杂的答案。 在我的特殊情况下,我找到了一个干净而简单的注销修复方法。 我还没有在 Edge 中进行测试。
在我登录的页面上,我放置了一个与此类似的注销链接:
在该 logout.html 页面(也受 .htaccess 保护)的头部,我有一个与此类似的页面刷新
:您可以保留“注销”一词,以清除为站点缓存的用户名和密码。
我承认,如果需要从一开始就直接登录多个页面,那么每个入口点都需要自己相应的 logout.html 页面。 否则,您可以通过在实际登录提示之前在流程中引入额外的网守步骤来集中注销,需要输入短语才能到达登录目的地。
There's a lot of great - complex - answers here. In my particular case i found a clean and simple fix for the logout. I have yet to test in Edge.
On my page that I have logged in to, I have placed a logout link similar to this:
And in the head of that logout.html page (which is also protected by the .htaccess) I have a page refresh similar to this:
Where you would leave the words "logout" in place to clear the username and password cached for the site.
I will admit that if multiple pages needed to be able to be directly logged in to from the beginning, each of those points of entry would need their own corresponding logout.html page. Otherwise you could centralize the logout by introducing an additional gatekeeper step into the process before the actual login prompt, requiring entry of a phrase to reach a destination of login.
我在一篇文章中总结了我的解决方案(https://www.hattonwebsolutions.co.uk/articles /how_to_logout_of_http_sessions)但是我使用了ajax调用和2x htaccess文件(正如这个问题中所建议的:如何注销HTTP身份验证(htaccess) 可以在 Google Chrome 中运行吗?)。
简而言之 - 您:
这可以避免注销文件夹中出现二次弹出窗口,请求另一个用户名(这会让用户感到困惑)。 我的文章使用了 Jquery 但应该可以避免这种情况。
I have summarised my solution in an article (https://www.hattonwebsolutions.co.uk/articles/how_to_logout_of_http_sessions) however I have used an ajax call and 2x htaccess files (as suggested in this question: How to logout of an HTTP authentication (htaccess) that works in Google Chrome?).
In short - you:
This avoids having a secondary popup in the logout folder requesting another username (which would confuse users). My article uses Jquery but it should be possible to avoid this.
我通过发送 401 标头实现了这一点。 这很好用。
使用 PHP
I achieved this with sending a 401 header. This works fine.
With PHP