通过PHP进行HTTP身份验证注销

2020/09/28 19:41 · php ·  · 0评论

注销HTTP身份验证受保护的文件夹正确方法是什么

有一些解决方法可以实现这一目标,但是它们可能会带来危险,因为它们可能有故障或在某些情况/浏览器中无法使用。这就是为什么我要寻找正确和清洁的解决方案。

亩。没有正确的方法,甚至没有跨浏览器一致的方法。

这是来自HTTP规范(第15.6节)的问题:

现有的HTTP客户端和用户代理通常会无限期地保留身份验证信息。HTTP / 1.1。没有为服务器提供一种方法来指示客户端丢弃这些缓存的凭据。

另一方面,第10.4.2说:

如果请求已包含授权凭证,则401响应指示已拒绝这些凭证的授权。如果401响应包含与先前响应相同的质询,并且用户代理已经尝试了至少一次身份验证,则应该向用户提供响应中给出的实体,因为该实体可能包含相关的诊断信息。

换句话说,您可以再次显示登录框(如@Karsten所说),但是浏览器不必满足您的请求 -因此,不要过多地依赖此功能。

在Safari中效果很好的方法。在Firefox和Opera中也可以使用,但带有警告。

Location: http://logout@yourserver.example.com/

这告诉浏览器使用新的用户名打开URL,覆盖新的用户名。

简单的答案是您无法可靠地注销http身份验证。

长答案:

Http-auth(与HTTP规范的其余部分一样)是无状态的。
因此,“登录”或“注销”并不是一个真正有意义的概念。看到它的更好方法是针对每个HTTP请求(记住页面加载通常是多个请求)询问“是否允许您执行请求的操作?”。服务器将每个请求视为新请求,并且与以前的任何请求都不相关。

浏览器已选择记住在第一个401上告诉您的凭据,然后在没有用户对后续请求的明确许可的情况下重新发送它们。这是尝试为用户提供他们期望的“已登录/已注销”模型,但这纯粹是一种错误。正是浏览器在模拟这种状态的持久性。Web服务器完全不知道它。

因此,在http-auth上下文中,“注销”纯粹是由浏览器提供的模拟,因此不在服务器权限范围内。

是的,有仇。但是它们破坏了RESTful-ness(如果这对您来说很有价值),并且它们不可靠。

如果您绝对需要登录/注销模型来进行站点认证,那么最好的选择是跟踪cookie,并以某种方式(mysql,sqlite,flatfile等)将状态的持久性存储在服务器上。这将要求评估所有请求,例如使用PHP。

解决方法

您可以使用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>

上面完成的是:

  • 对于IE-只需清除身份验证缓存并重定向到某处

  • 对于其他浏览器 -在后台使用“注销”登录名和密码发送XMLHttpRequest。我们需要将其发送到某个路径,该路径将对该请求返回200 OK(即,它不需要HTTP身份验证)。

更换'/where/to/redirect'一些路径注销后重定向到并替换'/path/that/will/return/200/OK'与您网站上的一些路径,将返回200 OK。

解决方法(不是一个干净的,不错的(甚至无法工作!请参见评论)解决方案):

一次禁用他的凭据。

您可以通过发送适当的标头(如果未登录)将HTTP身份验证逻辑移至PHP:

Header('WWW-Authenticate: Basic realm="protected area"');
Header('HTTP/1.0 401 Unauthorized');

并使用以下命令解析输入:

$_SERVER['PHP_AUTH_USER'] // httpauth-user
$_SERVER['PHP_AUTH_PW']   // httpauth-password

因此,一次禁用他的凭据应该是微不足道的。

分两个步骤从HTTP Basic Auth注销

假设我有一个名为“密码保护”的HTTP基本身份验证领域,Bob已登录。要注销,我发出2个AJAX请求:

  1. 访问脚本/ logout_step1。它将随机的临时用户添加到.htusers,并使用其登录名和密码进行响应。
  2. 使用临时用户的登录名和密码对访问脚本/ logout_step2进行身份验证该脚本删除临时用户,并在响应中添加此标头:WWW-Authenticate: Basic realm="Password protected"

此时,浏览器忘记了Bob的凭据。

我对这个问题的解决方法如下。您可以找到该函数http_digest_parse$realm并且$users在此页面的第二个示例中:http : //php.net/manual/zh/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;
}

通常,一旦浏览器要求用户提供凭据并将其提供给特定的网站,它将继续这样做而无需进一步提示。与可以在客户端清除cookie的各种方法不同,我不知道有类似的方法要求浏览器忘记其提供的身份验证凭据。

Trac(默认情况下)也使用HTTP身份验证。注销不起作用,无法解决:

  • 这是HTTP身份验证方案本身的问题,在Trac中我们无法采取任何措施来正确修复它。
  • 当前尚没有适用于所有主要浏览器的解决方法(JavaScript或其他)。

来自: http : //trac.edgewall.org/ticket/791#comment : 103

看起来该问题没有有效的答案,该问题已在7年前报告过,这很合理:HTTP是无状态的。是否使用身份验证凭据来完成请求。但这是客户端发送请求的问题,而不是服务器接收请求的问题。服务器只能说出请求URI是否需要授权。

我需要重置.htaccess授权,所以我使用了以下方法:

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
}
?>

在这里找到它:http :
//php.net/manual/en/features.http-auth.php

去搞清楚。

该页面上有很多解决方案,甚至在底部都有说明:Lynx,不会像其他浏览器一样清除auth;)

我在已安装的浏览器上对其进行了测试,并且一旦关闭,每个浏览器似乎始终需要在重新输入时进行重新验证。

这可能不是寻找的解决方案,但我这样解决了。我有2个用于注销过程的脚本。

logout.php

<?php
header("Location: http://.@domain.com/log.php");
?>

log.php

<?php
header("location: https://google.com");
?>

这样,我不会收到警告,并且会话会终止

AFAIK,使用htaccess(即基于HTTP)的身份验证时,没有干净的方法来实现“注销”功能。

这是因为此类身份验证使用HTTP错误代码“ 401”来告诉浏览器需要凭据,这时浏览器会提示用户输入详细信息。从那时起,直到关闭浏览器,浏览器将始终发送凭据,而无需进一步提示。

到目前为止,我发现的最佳解决方案是(这是一种伪代码,$isLoggedIn对于http auth而言,它是伪变量):

在“注销”时,只需将一些信息存储到会话中即可表明该用户实际上已注销。

function logout()
{
  //$isLoggedIn = false; //This does not work (point of this question)
  $_SESSION['logout'] = true;
}

在我检查身份验证的地方,我扩展了条件:

function isLoggedIn()
{
  return $isLoggedIn && !$_SESSION['logout'];
}

会话在某种程度上与http身份验证的状态相关联,因此只要用户保持浏览器打开以及http身份验证在浏览器中持续存在,用户就保持注销状态。

也许我错过了重点。

我发现结束HTTP身份验证的最可靠方法是关闭浏览器和所有浏览器窗口。您可以使用Javascript关闭浏览器窗口,但我认为您无法关闭所有浏览器窗口。

我发现清除PHP_AUTH_DIGESTor PHP_AUTH_USERAND PHP_AUTH_PW凭据的唯一有效方法是调用标头HTTP/1.1 401 Unauthorized

function clear_admin_access(){
    header('HTTP/1.1 401 Unauthorized');
    die('Admin access turned off');
}

当其他人在说,是正确的它不可能从基本的HTTP认证注销有实现其认证的方式表现相似。一种明显的方法是使用auth_memcookie如果您确实想使用此方法来实现基本的HTTP身份验证(即使用浏览器对话框登录而不是HTTP形式),只需将身份验证设置为一个单独的.htaccess保护目录,其中包含一个PHP脚本,该脚本会将用户重定向到后面的位置创建内存缓存会话。

这里有很多很棒的-复杂的-答案。在我的特殊情况下,我找到了一个干净而简单的注销解决方法。我尚未在Edge中进行测试。在我登录的页面上,放置了一个类似于以下内容的注销链接:

<a href="https://MyDomainHere.net/logout.html">logout</a>

在该logout.html页面(也受.htaccess保护)的顶部,我有一个类似于以下内容的页面刷新:

<meta http-equiv="Refresh" content="0; url=https://logout:logout@MyDomainHere.net/" />

您将在其中保留“注销”字样的位置以清除为站点缓存的用户名和密码。

我将承认,如果需要从一开始就可以直接登录多个页面,那么每个入口点都需要各自的相应logout.html页面。否则,您可以通过在实际登录提示之前在过程中引入一个额外的网守步骤来集中注销,这需要输入短语才能到达登录目标。

我已经在文章(https://www.hattonwebsolutions.co.uk/articles/how_to_logout_of_http_sessions)中总结了我的解决方案,但是我使用了ajax调用和2x htaccess文件(如该问题的建议:如何注销HTTP身份验证) (htaccess)是否可以在Google Chrome浏览器中使用?)。

简而言之-您:

  1. 在同一AuthName上创建一个带有htaccess文件的子文件夹,但需要其他用户
  2. 将ajax请求发送到页面(使用错误的用户名)(失败),然后触发超时重定向到注销的页面。

这样可以避免在注销文件夹中出现第二个弹出窗口,以请求另一个用户名(这会使用户感到困惑)。我的文章使用Jquery,但应该可以避免这种情况。

本文地址:http://php.askforanswer.com/tongguophpjinxinghttpshenfenyanzhengzhuxiao.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!