lxg524963880 2024-03-09 11:50 采纳率: 33.3%
浏览 4

php使用curl进行digest认证提示401错误

提示错误401,Invalid Operation,请问这个问题怎么解决啊

  <?php
          $username = '****';
          $password = '****';
          $uri = "/ISAPI/System/deviceInfo";
          $locla_url = 'http://****:8001';
          $url = $locla_url .$uri;

          $ch = curl_init();
          curl_setopt($ch,CURLOPT_URL, $url);
          curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
          curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);
          curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
          curl_setopt($ch,CURLOPT_FOLLOWLOCATION, false);
          curl_setopt($ch,CURLOPT_TIMEOUT, 30);
          curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 30);
          curl_setopt($ch,CURLOPT_CUSTOMREQUEST, "GET");
          curl_setopt($ch, CURLOPT_HEADER, 1);
          $first_response = curl_exec($ch);
          $info = curl_getinfo($ch);
          preg_match('/WWW-Authenticate: Digest (.*)/', $first_response, $matches);
          preg_match('/Set-Cookie: (.*)/', $first_response, $SessionIDmatches);
          if(!empty($matches))
              {
                $auth_header = $matches[1];
                $auth_header_array = explode(',', $auth_header);
                $parsed = array();

                foreach ($auth_header_array as $pair)
                {
                  $vals = explode('=', $pair);
                  $parsed[trim($vals[0])] = trim($vals[1], '" ');
                }
                $cnonce = rand(10000000,99999999);
                $nc = '00000001';
                $response_realm     = (isset($parsed['realm'])) ? $parsed['realm'] : "";
                $response_nonce     = (isset($parsed['nonce'])) ? $parsed['nonce'] : "";
                $response_opaque    = (isset($parsed['opaque'])) ? $parsed['opaque'] : "";
                
                $authenticate1 = md5($username.":".$response_realm.":".$password);
                $authenticate2 = md5("GET:".$uri);
              
                $authenticate_response = md5($authenticate1.":".$response_nonce.":".$nc.":".$cnonce.":".$parsed['qop'].":".$authenticate2);
              
                
                $request = sprintf('Authorization: Digest username="%s", realm="%s", nonce="%s", uri="%s", algorithm="MD5", response="%s", qop="%s", nc="%s", cnonce="%s"',
                $username, $response_realm, $response_nonce, $uri, $authenticate_response,$parsed['qop'],$nc,$cnonce);
                //$requestcookie = 'Cookie: '.$SessionIDmatches['1'];
                $request_header = array("Content-Type: application/json",$request); 
                $ch = curl_init();
                curl_setopt($ch,CURLOPT_URL, $url);
                curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, false);
                curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch,CURLOPT_FOLLOWLOCATION, true);
                curl_setopt($ch,CURLOPT_TIMEOUT, 30);
                curl_setopt($ch,CURLOPT_CONNECTTIMEOUT, 30);
                curl_setopt($ch,CURLOPT_CUSTOMREQUEST, "GET");
                curl_setopt($ch,CURLOPT_HTTPHEADER, $request_header);
           
                $result['response']         = curl_exec($ch);
                $result['info']             = curl_getinfo ($ch);
                $result['info']['errno']    = curl_errno($ch);
                $result['info']['errmsg']   = curl_error($ch);
                curl_close($ch);
                print_r($result['response']);
                
            }

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-09 11:50
    关注

    引自免费微信小程序:皆我百晓生

    在您的PHP代码中,您正在尝试使用cURL进行Digest认证来访问一个受保护的资源。错误401表示未经授权,这通常意味着服务器未接受您的身份验证信息。根据您提供的代码片段,以下是一些可能的问题和相应的解决方案:

    1. Nonce和Opaque值处理: 确保正确地从服务器响应中提取nonce和opaque值,并且在构建Authorization头时正确地使用它们。有时,服务器可能会提供额外的属性,比如algorithmdomainstale等,需要检查并适当地包含在请求头里。

    2. QOP值: 检查parsed['qop']是否存在并且正确。Digest认证中的Quality of Protection (qop) 可能是"auth", "auth-int"或其他类型。如果服务器要求特定的qop但未正确设置,则可能导致认证失败。

    3. NC(Nonce Count): 在每次重新认证时,NC值应递增。例如,在第二次请求时,NC应该变为'00000002',以此类推。您当前代码始终将其设置为'00000001'。

    4. CURL请求头设置: 确保在第二次发送GET请求时,HTTP头已经被正确地设置。这里看起来没有问题,但是为了确保准确性,请确认所有变量都已正确填充,并且在构建Authorization头时没有任何拼写错误或遗漏。

    5. Cookie处理: 虽然您注释掉了处理Session ID的代码,但如果服务器依赖于Cookie进行身份验证,请确保启用Cookie传递。可以取消注释相关代码并添加到请求头数组中。

    6. 错误排查: 使用curl_errno()和curl_error()获取更具体的错误信息有助于定位问题所在。您可以输出这些信息以查看是否有其他提示性错误。

    修改后的部分代码示例:

    ...
    // 增加NC计数逻辑,假设这是首次请求后的重试
    $nc = sprintf('%08d', 1 + intval($parsed['nc'] ?? 0)); // 自动递增nonce count
    
    ...
    
    // 检查parsed['qop']是否存在并赋值给$qop变量
    $qop = isset($parsed['qop']) ? $parsed['qop'] : '';
    
    // 构造Authorization头
    $request = sprintf('Authorization: Digest username="%s", realm="%s", nonce="%s", uri="%s", algorithm="MD5", response="%s", qop="%s", nc="%s", cnonce="%s"',
        $username, $response_realm, $response_nonce, $uri, $authenticate_response, $qop, $nc, $cnonce);
    
    // 如果需要,取消注释下面的行以添加Cookie头
    // $request_cookie = 'Cookie: '.$SessionIDmatches['1'];
    // $request_header = array("Content-Type: application/json", $request, $request_cookie); 
    
    $request_header = array("Content-Type: application/json", $request); 
    ...
    
    // 输出错误信息以便调试
    if ($result['info']['errno'] !== CURLE_OK) {
        echo "Error: [" . $result['info']['errno'] . "] " . $result['info']['errmsg'];
    }
    
    print_r($result['response']);
    

    最后,请确保目标服务器支持并配置了正确的Digest认证机制。如果服务器配置有误或者API文档中有特殊的身份验证要求,请参照相应文档进行调整。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 3月9日

悬赏问题

  • ¥200 基于同花顺supermind的量化策略脚本编辑
  • ¥20 Html备忘录页面制作
  • ¥15 黄永刚的晶体塑性子程序中输入的材料参数里的晶体取向参数是什么形式的?
  • ¥20 数学建模来解决我这个问题
  • ¥15 计算机网络ip分片偏移量计算头部是-20还是-40呀
  • ¥15 stc15f2k60s2单片机关于流水灯,时钟,定时器,矩阵键盘等方面的综合问题
  • ¥15 YOLOv8已有一个初步的检测模型,想利用这个模型对新的图片进行自动标注,生成labellmg可以识别的数据,再手动修改。如何操作?
  • ¥30 NIRfast软件使用指导
  • ¥20 matlab仿真问题,求功率谱密度
  • ¥15 求micropython modbus-RTU 从机的代码或库?