PHP HTTP Digest校验

PHP作为客户端进行HTTP Digest校验

// 请求方法
          $username = 'admin';
          $password = 'admin123';
          $uri = "api/cgi-bin/subscribe/picture";
          $url = $this->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(1000000000000000,9999999999999999);
                $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("POST:".$url);

                $authenticate_response = md5($authenticate1.":".$response_nonce.":".$nc.":".$cnonce.":".$parsed['qop'].":".$authenticate2);

                $request = sprintf('Authorization: Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s", qop="%s", nc="%s", cnonce="%s"',
                $username, $response_realm, $response_nonce, $url, $authenticate_response,$parsed['qop'],$nc,$cnonce);
                $requestcookie = 'Cookie: '.$SessionIDmatches['1'];
                $request_header = array($request,$requestcookie); 
                
                $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, "POST");
                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);
                 
            }

当客户端发起任意接口访问请求与设备建立会话时,设备会检查session是否有效(进行过digest校验并校验未失效的session为有效的session),设备只会对session有效客户端正常响应.

当客户端发起访问的session无效时,
设备返回401链接状态.
WWW-Authenticate字段返回校验用的参数.
Set-Cookie字段返回新的session.

当客户端检测到401链接状态,读取http头中的校验信息进行digest校验的计算
获得在WWW-Authenticate字段中附带的realm,qop,nonce,opaque等参数
集合客户端的username,password,cnonce,nc等参数
按照qop计算校验码(在本系统的校验中qop的值为auth,所以按照如下方式计算)

A1 = username:realm:password
A2 = mthod:uri
HA1 = MD5(A1)
HA2 = MD5(A2)
response = MD5(HA1:nonce:nc:cnonce:qop:HA2)

计算出response之后,再一次发起访问的请求,在Authorization中添加校验相关参数与和返回中获取的Cookie发送到设备
设备会根据收到的校验信息,与使用存在设备当中的密码计算出的校验码比较,来确认客户的身份(账号密码)是否正确,校对通过则开始正常通信
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要用C语言实现HTTP Digest登录,需要进行以下步骤: 1. 创建HTTP Digest请求头部。HTTP Digest登录需要在请求头部添加Authorization字段,其中包含了用户名、密码、请求方法、URI等信息的摘要。要创建这个请求头部,可以使用OpenSSL库中的md5函数来计算摘要。 2. 发送HTTP请求。可以使用C语言的socket库来建立连接并发送HTTP请求。在发送请求时,需要将创建的请求头部添加到HTTP请求的头部中。 3. 接收HTTP响应。使用socket库从服务器接收HTTP响应,然后对响应进行解析,判断是否登录成功。 以下是一个简单的C语言HTTP Digest登录的代码示例: ```c #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <openssl/md5.h> // HTTP请求头部中的Authorization字段 void make_http_digest_auth(char *username, char *password, char *method, char *uri, char *realm, char *nonce, char *cnonce, char *qop, char *nc, char *digest) { char ha1[MD5_DIGEST_LENGTH]; char ha2[MD5_DIGEST_LENGTH]; char response[MD5_DIGEST_LENGTH]; // 计算HA1 char ha1_str[1024]; snprintf(ha1_str, sizeof(ha1_str), "%s:%s:%s", username, realm, password); MD5((unsigned char*)ha1_str, strlen(ha1_str), (unsigned char*)ha1); // 计算HA2 char ha2_str[1024]; snprintf(ha2_str, sizeof(ha2_str), "%s:%s", method, uri); MD5((unsigned char*)ha2_str, strlen(ha2_str), (unsigned char*)ha2); // 计算response char response_str[1024]; snprintf(response_str, sizeof(response_str), "%s:%s:%s:%s:%s:%s", ha1, nonce, nc, cnonce, qop, ha2); MD5((unsigned char*)response_str, strlen(response_str), (unsigned char*)response); // 组装Authorization字段 snprintf(digest, 1024, "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\", cnonce=\"%s\", nc=%s, qop=%s", username, realm, nonce, uri, response, cnonce, nc, qop); } int main() { int sockfd; struct sockaddr_in servaddr; // 创建socket sockfd = socket(AF_INET, SOCK_STREAM, 0); // 设置服务器地址 memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(80); inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); // 连接服务器 connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); // 创建HTTP Digest请求头部 char digest[1024]; char *username = "user"; char *password = "password"; char *method = "GET"; char *uri = "/"; char *realm = "test"; char *nonce = "123456"; char *cnonce = "654321"; char *qop = "auth"; char *nc = "00000001"; make_http_digest_auth(username, password, method, uri, realm, nonce, cnonce, qop, nc, digest); // 发送HTTP请求 char request[1024]; snprintf(request, 1024, "GET / HTTP/1.1\r\nHost: localhost\r\nAuthorization: %s\r\n\r\n", digest); write(sockfd, request, strlen(request)); // 接收HTTP响应 char response[1024]; int len = read(sockfd, response, 1024); response[len] = '\0'; printf("%s", response); // 关闭socket close(sockfd); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值