相关视频学习链接:
B站视频链接TR069协议与商业应用
腾讯课堂视频链接TR069协议与商业应用
TR069 Http Digest 认证流程
一 流程及流程图
1.1盒端主动发起Http Digest认证流程
盒端CPE ACS终端管理系统
1.------------------inform(http不带auth头)----------->
2.<------------------401(http不带auth头)--------------
3.------------------inform(http带auth头)------------->
4.<------------------200 OK---------------------------
5.------------------ Content-Length: 0--------------->
机顶盒(CPE)通过HTTP Digest Authentication发起与终端管理系统(ACS)的认证连接,连接方式遵循RFC 2617的规定。
机顶盒连接终端管理系统的地址由Device.ManagementServer.URL参数提供。
机顶盒主动想终端管理系统发起一个HTTP 连接请求,终端管理系统会要求进行HTTP Digest Authentication认证。并按照RFC2671规范,盒端和盒端管理系统在之后的请求和应答时信息均带有认证头信息。
认证中的用户名、密码为Device.ManagementServer.Username 及Device.ManagementServer.Password
1.2 ACS主动发起Http Digest认证流程
盒端CPE ACS终端管理系统
1.<------------------http(不带auth头信息)-------------
2.------------------ 401 Unauthorized---------------->
3.<------------------http get(带auth头信息)-----------
4.------------------200 OK--------------------------->
5.<-----------------100 continue----------------------
6.------------------6 connect request---------------->
7.<------------------200 OK---------------------------
ACS终端管理系统主动发起一个HTTP 请求,CPE终端会要求进行HTTP Digest Authentication认证。并按照RFC2671规范,盒端和盒端管理系统在之后的请求和应答时信息均带有认证头信息。
认证中的用户名、密码为Device.ManagementServer.Connection.RequestUsername及Device.ManagementServer.ConnectionRequestPassword
二 详细交互流程:
2.1 盒端主动发起Http Digest认证报文
CPE IP地址: 192.168.20.11
ACS IP地址: 192.168.20.36
1)盒端(CPE)首先发起不带认证头的Inform请求报文,内容如下:
POST /acs HTTP/1.1
Host: 192.168.20.36
Accept: /
Connection: TE, Keep-Alive
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 3814
Expect: 100-continue
HTTP/1.1 100 Continue
1
Test
A1B2C4
Test_PC
821281000054321
1 BOOT
……..
2) 盒端管理系统(ACS)收到上述报文后,发现没有认证消息(带有Authorization:标识的报文),然后发送401错误报文:
HTTP/1.1 401 Unauthorized
Date: Fri, 06 Jan 2017 02:47:12 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONID=12rxzt10p2rtb;Path=/
Content-Type: text/xml; charset=utf-8
WWW-Authenticate: Digest realm="XACS",qop="auth",nonce="fd171d5efcc65e79bfd8150af7f9//代码效果参考:http://www.jhylw.com.cn/224237119.html
cb21"Content-Length: 0
Server: Jetty(6.1.20)
3 ) 盒端(cpe)收到报文后,经过分析得到报文错误为401,代码中通过分析报文中是否有WWW-Authenticate: Digest 字段,如果具有那么通过设置函数
//设置鉴权参数
code=curl_easy_setopt(curl,CURLOPT_HTTPAUTH,CURLAUTH_BASIC|CURLAUTH_DIGEST);
(本地配置的realm必须与收到的realm一致否则验证不能通过)将本地文件配置的realm和从盒端管理系统(ACS)收到的nonce,opaque,qop等值通过函数http_da_calc_HA1,生成一个唯一的字符串并存入response字段,并将这些信息组合到报文的头部,最后发送给ACS的报文为:
POST /acs HTTP/1.1
Authorization: Digest username="cpe", realm="XACS", nonce="fd171d5efcc65e79bfd8150af7f9cb21", uri="/acs", cnonce="MDQ1NzA0", nc=00000001, qop="auth", response="5f6059675ea5da97e45be615c2466ff7"
Host: 192.168.20.36
Accept: /
Cookie: JSESSIONID=12rxzt10p2rtb
Connection: TE, Keep-Alive
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 3814
Expect: 100-continue
HTTP/1.1 100 Continue
//代码效果参考:http://www.jhylw.com.cn/375730839.html
1Test
A1B2C4
Test_PC
821281000054321
1 BOOT
……….
…….
4)盒端管理系统(ACS)收到上述报文后,确认其含Authorization:字段,并且Authorization:字段中的response的值正确,那么认证通过,并发送回复报文:
HTTP/1.1 200 OK
Date: Fri, 06 Jan 2017 02:47:12 GMT
Content-Type: text/xml; charset=utf-8
Content-Length: 526
Server: Jetty(6.1.20)
101
5) 盒端(CPE)收到回复报文后,分析为认证通过报文后,发送一个inform内容为空的确认报文:——其实就是个空报文
POST /acs HTTP/1.1
Authorization: Digest username="cpe", realm="XACS", nonce="fd171d5efcc65e79bfd8150af7f9cb21", uri="/acs", cnonce="MDQ1NzA0", nc=00000002, qop="auth", response="1b58ed5321c916998e4af9de375177fc"
Host: 192.168.20.36
Accept: /
Cookie: JSESSIONID=12rxzt10p2rtb
Connection: TE, Keep-Alive
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
2.2 ACS主动发起Http Digest认证报文
略,和2.1流程类似,具体可以下载报文,自行分析。
2.3 同时开启双向认证
即CPE终端认证ACS管理系统,和ACS管理系统认证CPE终端同时认证。成功后盒端和盒端管理系统在之后的请求和应答时信息均带有认证头信息,认证中的用户名、密码为Device.ManagementServer.Username 及Device.ManagementServer.Password
报文下载路径:
三 代码片段:
1) CPE 认证ACS管理系统的代码
//初始化curl库,设置参数用于http 传输
1 int http_init_curl(cwmp_context_t cwmp_ctx, t_MemStruct pmem, CURL *pcurl)
2
3 {
4
5 CURLcode code;
6
7 CURL curl = NULL;
8
9 char acs_usr = NULL;
10
11 char acs_passwd = NULL;
12
13 char error_buf【CURL_ERROR_SIZE】;
14
15 CURLcode ret = FALSE;
16
17
18
19
20
21 if(!cwmp_ctx || !pmem || !pcurl)
22
23 {
24
25 CWMP_LOG_ERROR(EVENT_MODULE, "some param is NULL\n");
26
27 return FALSE;
28
29 }
30
31
32
33 curl = curl_easy_init();
34
35 if (!curl)
36
37 {
38
39 CWMP_LOG_ERROR(EVENT_MODULE, "curl_easy_init fail\n");
40
41 return FALSE;
42
43 }
44
45
46
47 memset(error_buf, 0, sizeof(error_buf));
48
49 code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buf);
50
51 if (code != CURLE_OK)
52
53 {
54
55 CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set error buffer 【%d】\n", code);
56
57 return FALSE;
58
59 }
60
61
62
63 //设置回写函数
64
65 code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cwmp_write_func_callback);
66
67 if (code != CURLE_OK)
68
69 {
70
71 CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set writer 【%s】\n", curl_easy_strerror(code));
72
73 goto finish;
74
75 }
76
77
78
79 code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)pmem);
80
81 if (code != CURLE_OK)
82
83 {
84
85 CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set write data 【%s】\n", curl_easy_strerror(code));
86
87 goto finish;
88
89 }
90
91
92
93 code = curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
94
95 if (code != CURLE_OK)
96
97 {
98
99 CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set cookie file 【%s】\n", curl_easy_strerror(code));
100
101 goto finish;
102
103 }
104
105
106
107 //设置鉴权参数
108
109 code = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST);
110
111 if (code != CURLE_OK)
112
113 {
114
115 CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set http auth 【%s】\n", curl_easy_strerror(code));
116
117 goto finish;
118
119 }
120
121 get_param_value_by_fullname(IGD_ManagementServer_Username, &acs_usr);
122
123 get_param_value_by_fullname(IGD_ManagementServer_Password, &acs_passwd);
124
125 if (acs_usr && acs_passwd)
126
127 {
128
129 //curl_easy_setopt(curl, CURLOPT_USERNAME, acs_usr);
130
131 //curl_easy_setopt(curl, CURLOPT_PASSWORD, acs_passwd);
132
133 code = curl_easy_setopt(curl, CURLOPT_USERNAME, acs_usr);
134
135 if (code != CURLE_OK)
136
137 {
138
139 CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set username 【%s】\n", curl_easy_strerror(code));
140
141 goto finish;
142
143 }
144
145 code = curl_easy_setopt(curl, CURLOPT_PASSWORD, acs_passwd);
146
147 if (code != CURLE_OK)
148
149 {
150
151 CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set password 【%s】\n", curl_easy_strerror(code));
152
153 goto finish;
154
155 }
156
157
158
159 CWMP_LOG_DEBUG(EVENT_MODULE, "acs usrname=%s, passwd=%s\n", acs_usr, acs_passwd);
160
161 }
162
163 else
164
165 {
166
167 CWMP_LOG_ERROR(EVENT_MODULE, <span style="color: rgba(128, 0, 0