C/S应用程序中进行HTTP登录,获取相应的资料。
来源:互联网 发布:黑马程序员 c 课件 编辑:程序博客网 时间:2024/04/27 23:21
前段时间处理三星的一个设备,用其的库时,登陆时需要指定设备类型,应用程序里相关的资料里也没有保存设备的类型字段,应用里在我不知道这个设备型号时,问厂家怎么解决,回复我说一个一个的设备类型去连接吧! 很变态呀,几个类型的设备试下来时间很长。由于他的设备支持HTTP,RTSP协议,在HTTP管理时,有一个页面是可以看到其设备类型的,一想,每一种设备都有WEB服务,都是同一样的接口,这样先登录时,我在应用程序里做一个WEB请求来获取其设备型号先,再用TCP去连接,而这个WEB服务是基本一直打开的。
看了一个其HTTP协议的说明,WEB的设备登录说是用RFC2069协议的"Standard http digest access authentication method of RFC2069"认证,了解的一下RFC2069,再用WireShark跟踪了登录过程, 其实也不是很Standard呀,很多细节不同的。
Delphi里有一个TIdDigestAuthentication类,就是用来实现这个的,不过这个是标准的,还是和设备的有一定的差异,HTTP请求反证就是一个有特定格式的字符串,所以我做一个类重载了它的Authentication方法:
TDigestAuth = class(TIdDigestAuthentication)
private
FWWWAuthenticate: string;
FBASEURI: string;
public
constructor Create(WWWAuthenticate,buri: string);
function Authentication: String;override;
property WWWAuthenticate: string read FWWWAuthenticate write FWWWAuthenticate;
property BASEURI: string read FBASEURI write FBASEURI;
end;
自己再在这个方法里生成特定的请求就好了:
function TDigestAuth.Authentication: String;
var
authtext,AuthorizationStr: string;
A1,A2,Method: string;
realm,nonce,uri,qop,cnonce,nc,response: string;
ipos,Steps: integer;
begin
authtext := WWWAuthenticate;
ipos := Pos('nonce="',authtext);
if ipos > 0 then
begin
Delete(authtext,1,ipos+6);
end;
ipos := pos('"',authtext);
if ipos > 0 then
begin
nonce := Copy(authtext,1,ipos-1);
end;
realm := 'iPolis';
qop := 'auth';
uri := BASEURI;
cnonce := '01a34a';
Steps := 1;
nc := Format('%.8d',[Steps]);
A1 := MD5Print(MD5String(UserName + ':' + realm + ':' + Password));
Method := 'GET';
A2 := MD5Print(MD5String(Method + ':' + uri));
response :=MD5Print(MD5String(A1+':'+nonce+':'+ nc + ':'+ cnonce + ':' + qop +':'+A2));
AuthorizationStr := Format('Digest username="%s",realm="%s",nonce="%s",uri="%s",'+
'cnonce="%s",nc=%s,response="%s",qop="%s"',
[UserName,realm,nonce,uri,cnonce,nc,response,qop]);
Result := AuthorizationStr;
end;
注意上面A1,A2,response的格式组成,这个是RFC上面是有标准的。可以参考这里:http://en.wikipedia.org/wiki/Digest_access_authentication
或下载一个RFC2069的文档看看。
上面这个方法返回的就是最终的请求登录时的HTTP内容了。
在应用的里面我再写一个如下的过程来登录和请求设备的类型:
function TXXXSAM.GetDeviceModelName: string;
function FromHtmlResponseGetModelName(ResponseText: string): string;
var
ts: TStringList;
i,iPos: integer;
modelStr: string;
begin
modelStr := '';
Result := '';
ResponseText := StringReplace(ResponseText,#13#10,'#',[rfReplaceAll]);
iPos := Pos('model',ResponseText);
modelStr := Copy(ResponseText,iPos,Length(ResponseText));
iPos := Pos('#',modelStr);
Result := Copy(modelStr,7,iPos-7);
end;
var
URL,uri:string;
IdHTTP: TIdHTTP;
ResponseStream: TStringStream;
DigestAuth: TDigestAuth;
begin
Result := '';
URL := Format('http://%s%s',[IP,SAMHTTPGETPARAM]);
uri := SAMHTTPGETPARAM;
IdHTTP := TIdHTTP.Create(nil);
ResponseStream := TStringStream.Create('');
try
try
ResponseStream.Seek(0,0);
IdHTTP.Get(URL,ResponseStream);
except
;
end;
if (IdHttp.ResponseCode = 401) and //401 请求登录
(pos('auth',IdHttp.Response.WWWAuthenticate.Text) > 0) then
begin
DigestAuth := TDigestAuth.Create(IdHttp.Response.WWWAuthenticate.Text,uri);
IdHTTP.Request.Authentication := DigestAuth;
IdHTTP.Request.Authentication.Username := self.UserName;
IdHTTP.Request.Authentication.Password := self.PassWord;
IdHTTP.Request.SetHeaders;
try
ResponseStream.Seek(0,0);
IdHttp.Get(URL,ResponseStream);
except
;
end;
if IdHttp.ResponseCode = 404 then //请求的页面不存在:三星的HTTP协议获取参数有多种类型,有的类型的地址不一样
begin
URL := Format('http://%s%s',[IP,SAMHTTPGETPARAM2]);
uri := SAMHTTPGETPARAM2;
DigestAuth.BASEURI := uri;
IdHTTP.Request.SetHeaders;
try
ResponseStream.Seek(0,0);
IdHttp.Get(URL,ResponseStream);
except
;
end;
end;
if IdHttp.ResponseCode = 200 then //成功
Result := FromHtmlResponseGetModelName(ResponseStream.DataString)
else if IdHTTP.ResponseCode = 401 then
LastMessageInfo := 'HTTP请求登录失败'
else
begin
LastMessageInfo := 'HTTP请求信息失败:'+ IdHttp.ResponseText;
writelog(SAMGetLastError(LastMessageInfo));
end;
end
else if IdHttp.ResponseCode = 200 then //成功
begin
Result := FromHtmlResponseGetModelName(ResponseStream.DataString);
end
else
begin
LastMessageInfo := 'HTTP请求信息失败:'+ IdHttp.ResponseText;
writelog(SAMGetLastError(LastMessageInfo));
end;
finally
ResponseStream.Free;
IdHTTP.Free;
end;
end;
- C/S应用程序中进行HTTP登录,获取相应的资料。
- 基于HTTP协议的C/S架构中服务器如何获取用户身份
- robotium 中通过id获取 View 以及进行相应的操作
- robotium 中通过id获取 View 以及进行相应的操作
- 对http相应中trunked的解析
- JS中获取表单的相应内容
- WEB应用程序中B/S与C/S架构的比较
- mongodb C/C++ driver 通过帐号验证登录mongo服务器并进行相应操作
- c#.net各种应用程序中获取文件路径的方法
- 从配置文件读取相应的信息加载到应用程序中
- 创建基于TCP的C/S应用程序
- C/S和B/S应用程序的本质区别
- C/S与B/S应用程序的比较
- C/S与B/S应用程序的比较
- 数据插入数据库中获取相应的主键值
- OC中获取系相应目录的几种方法
- ASP.NET跨应用程序进行登录的解决
- ASP.NET跨应用程序进行登录的解决
- c# winform取全屏幕大小
- 清华大学韩顺平讲师讲算法之三(上),高性能计算器堆之应用
- 起码我们曾经爱过,不是吗
- 修改用户进程可打开文件数限制
- HDU 3724 Encoded Barcodes(字典树,计算前缀数)
- C/S应用程序中进行HTTP登录,获取相应的资料。
- 算法感悟
- 清华大学韩顺平讲师讲算法之三(下),环链表创建与删除
- 华为交换机注释零-视图切换
- 程序以及体会
- vc自画窗体 黑边去除
- 8中食物抗衰老
- 巴黎雨季的伤感空间日志发布:喜欢在两个完全不同的世界
- oracle 11g 学习笔记 2012_10_25(a)