Jos*_*ábl 149 php authentication .htaccess password-protection http-headers
注销HTTP身份验证保护文件夹的正确方法是什么?
有一些解决方法可以实现这一点,但它们具有潜在的危险性,因为它们可能是错误的,或者在某些情况/浏览器中不起作用.这就是为什么我正在寻找正确和干净的解决方案.
Pis*_*3.0 102
亩.没有正确的方法,甚至没有一个跨浏览器一致的方式.
这是来自HTTP规范的问题(第15.6节):
现有的HTTP客户端和用户代理通常会无限期地保留身份验证信息.HTTP/1.1.没有提供服务器指示客户端丢弃这些缓存凭据的方法.
另一方面,第10.4.2节说:
如果请求已包含授权凭据,则401响应表示已拒绝授权这些凭据.如果401响应包含与先前响应相同的挑战,并且用户代理已经尝试过至少一次认证,则应该向用户呈现响应中给出的实体,因为该实体可能包括相关的诊断信息.
换句话说,您可以再次显示登录框(如@Karsten所说),但浏览器不必遵守您的请求 - 因此不要过多依赖此(错误)功能.
Kor*_*nel 59
在Safari中很好地工作的方法.也适用于Firefox和Opera,但有警告.
Location: http://logout@yourserver.example.com/
Run Code Online (Sandbox Code Playgroud)
这告诉浏览器使用新用户名打开URL,覆盖前一个用户名.
Jon*_*son 46
简单的答案是您无法可靠地注销http身份验证.
答案很长:
Http-auth(与HTTP规范的其余部分一样)意味着无状态.因此,"登录"或"退出"并不是一个有意义的概念.更好的方法是询问每个HTTP请求(并记住页面加载通常是多个请求),"你被允许做你要求的吗?".服务器将每个请求视为新请求,与先前的任何请求无关.
浏览器选择记住您在第一个401上告诉他们的凭据,并在没有用户对后续请求的明确许可的情况下重新发送它们.这是为了向用户提供他们期望的"登录/注销"模型,但它纯粹是一种kludge.这是模拟这种状态持久性的浏览器.Web服务器完全没有意识到它.
因此,在http-auth的上下文中"注销"纯粹是由浏览器提供的模拟,因此在服务器的权限之外.
是的,有kludges.但是他们打破了RESTful-ness(如果这对你有价值的话)并且它们是不可靠的.
如果您绝对需要登录/注销模型进行站点身份验证,最好的选择是跟踪cookie,状态的持久性以某种方式存储在服务器上(mysql,sqlite,flatfile等).这将要求评估所有请求,例如,使用PHP.
小智 26
解决方法
你可以使用Javascript来做到这一点:
<html><head>
<script type="text/javascript">
function logout() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
// code for IE
else if (window.ActiveXObject) {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if (window.ActiveXObject) {
// IE clear HTTP Authentication
document.execCommand("ClearAuthenticationCache");
window.location.href='/where/to/redirect';
} else {
xmlhttp.open("GET", '/path/that/will/return/200/OK', true, "logout", "logout");
xmlhttp.send("");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {window.location.href='/where/to/redirect';}
}
}
return false;
}
</script>
</head>
<body>
<a href="#" onclick="logout();">Log out</a>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
上面做的是:
对于IE - 只需清除身份验证缓存并重定向到某个地方
对于其他浏览器 - 使用'logout'登录名和密码在幕后发送XMLHttpRequest.我们需要将它发送到某个路径,该路径将向该请求返回200 OK(即它不应该要求HTTP身份验证).
'/where/to/redirect'在注销后替换为某些路径以重定向到并替换'/path/that/will/return/200/OK'为您的站点上将返回200 OK的某个路径.
Kar*_*ten 13
解决方法(不是干净,漂亮(甚至工作!请参阅注释)解决方案):
一次禁用他的凭据.
您可以通过发送相应的标头(如果未登录)将HTTP身份验证逻辑移动到PHP:
Header('WWW-Authenticate: Basic realm="protected area"');
Header('HTTP/1.0 401 Unauthorized');
Run Code Online (Sandbox Code Playgroud)
并使用以下方法解析输入:
$_SERVER['PHP_AUTH_USER'] // httpauth-user
$_SERVER['PHP_AUTH_PW'] // httpauth-password
Run Code Online (Sandbox Code Playgroud)
因此,一次禁用他的凭据应该是微不足道的.
我对此问题的解决方案如下.你可以找到的功能http_digest_parse,$realm并$users在此页的第二个例子:http://php.net/manual/en/features.http-auth.php.
session_start();
function LogOut() {
session_destroy();
session_unset($_SESSION['session_id']);
session_unset($_SESSION['logged']);
header("Location: /", TRUE, 301);
}
function Login(){
global $realm;
if (empty($_SESSION['session_id'])) {
session_regenerate_id();
$_SESSION['session_id'] = session_id();
}
if (!IsAuthenticated()) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.$_SESSION['session_id'].'",opaque="'.md5($realm).'"');
$_SESSION['logged'] = False;
die('Access denied.');
}
$_SESSION['logged'] = True;
}
function IsAuthenticated(){
global $realm;
global $users;
if (empty($_SERVER['PHP_AUTH_DIGEST']))
return False;
// check PHP_AUTH_DIGEST
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
!isset($users[$data['username']]))
return False;// invalid username
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
// Give session id instead of data['nonce']
$valid_response = md5($A1.':'.$_SESSION['session_id'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if ($data['response'] != $valid_response)
return False;
return True;
}
Run Code Online (Sandbox Code Playgroud)
假设我有一个名为"密码保护"的HTTP Basic Auth领域,并且Bob已登录.要注销,我发出2个AJAX请求:
WWW-Authenticate: Basic realm="Password protected"此时浏览器忘记了Bob的凭据.
我发现消除PHP_AUTH_DIGESTor PHP_AUTH_USERANDPHP_AUTH_PW凭据的唯一有效方法是调用 header HTTP/1.1 401 Unauthorized。
function clear_admin_access(){
header('HTTP/1.1 401 Unauthorized');
die('Admin access turned off');
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
109565 次 |
| 最近记录: |