| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- unit JITAuth;
- interface
- uses
- xmldom, XMLIntf, msxmldom, XMLDoc, Classes, SysUtils, Dialogs, LoggerImport,
- mybean.core.objects, InterfaceCA, IdHTTP, Forms;
- type
- SHeadInfo = Record
- Version:String;
- ServiceType:String;
- AuthResult:String;
- ErrorCode:String;
- ErrorDesc:String;
- end;
- SBodyInfo = Record
- AuthMode:String;
- AuthResult:String;
- AccessControlResult:String;
- AttrList:TStringList;
- end;
- TJITAuth = class(TMyBeanInterfacedObject, ICAClient)
- private
- function RandomNum: string;
- function GetNodeAttributeValue(xmlNode:IXMLNode; strAttribute:String):String;
- procedure ParseHeadNode(HeadNode:IXMLNode; var HeadInfo: SHeadInfo);
- procedure ParseRootNode(RootNode:IXMLNode; var HeadInfo:SHeadInfo; var BodyInfo:SBodyInfo);
- procedure ParseBodyNode(BodyNode:IXMLNode; var BodyInfo: SBodyInfo);
- function GenRandom: String;
- procedure InitRequestHead(AIdHttp: TIdHttp);
- function RequestUserJsonBySubjectDN(ASubjectDN: string): string;
- public
- function Request: string; stdcall;
- end;
- implementation
- uses
- JITComVCTKLib_TLB, CAImport, Windows, StrUtils, AppCentreImport, InterfaceAppCentre;
- function SplitString(const Source, Ch:string): TStringList;
- var
- Temp: string;
- iLoop: Integer;
- begin
- Result := TStringList.Create;
- Temp := Source;
- iLoop := Pos(Ch, Source);
- while iLoop <> 0 do
- begin
- Result.Add(copy(temp, 0, iLoop-1));
- Delete(temp, 1, iLoop);
- iLoop := Pos(Ch, Temp);
- end;
- Result.Add(temp);
- end;
- { TJITAuth }
- function TJITAuth.RandomNum: string;
- const
- CHS: string = '1234567890abcdefghijklmnopqrstopqrstuvwxyz';
- ASIZE: Integer = 6;
- var
- iLoop: Integer;
- key: array[0..5] of char;
- begin
- Randomize;
- for iLoop := 0 to ASIZE - 1 do
- key[iLoop] := CHS[Random(36)];
- Result := string(key);
- end;
- procedure TJITAuth.InitRequestHead(AIdHttp: TIdHttp);
- begin
- AIdHttp.Request.Accept := 'text/html, */*';
- AIdHttp.Request.ContentType := 'text/xml';
- AIdHttp.AllowCookies := True;
- AIdHttp.ProxyParams.BasicAuthentication := False;
- AIdHttp.ProxyParams.ProxyPort := 0;
- AIdHttp.Request.ContentLength := -1;
- AIdHttp.Request.ContentRangeEnd := 0;
- AIdHttp.Request.ContentRangeStart := 0;
- AIdHttp.Request.ContentType := 'text/xml';
- AIdHttp.Request.Accept := 'text/html, */*';
- AIdHttp.Request.BasicAuthentication := False;
- AIdHttp.HTTPOptions := [hoForceEncodeParams];
- end;
- function TJITAuth.GenRandom: String;
- var
- ReponseData, HostAddr, PostMsg:String;
- StrStream:TStringStream;
- RootNode:IXMLNode;
- ChildNodes, BodyChildNode:IXMLNodeList;
- BodyNode, TempNode:IXMLNode;
- I,J:Integer;
-
- PostStream:TStringStream;
- AConfig: ICAConfig;
- AIdHttp: TIdHttp;
- AXMLDoc: TXMLDocument;
- begin
- AConfig := GetCAConfig;
- Result:= '';
- PostMsg := '<?xml version="1.0" encoding="UTF-8"?>'
- + '<message>'
- + '<head>'
- + '<version>1.0</version>'
- + '<serviceType>OriginalService</serviceType>'
- + '</head>'
- + '<body>'
- + '<appId>' + AConfig.GetAppID + '</appId>'
- + '</body>'
- + '</message>';
- PostStream:=TStringStream.Create(AnsiToUtf8(PostMsg));
- HostAddr := AConfig.GetURL;
- AIdHttp := TIdHTTP.Create(nil);
- InitRequestHead(AIdHttp);
- try
- ReponseData:= AIdHttp.Post(AConfig.GetURL, PostStream);
- except
- on Ex: Exception do
- begin
- ShowMessage('CA服务器可能不存在,详细错误:' + Ex.Message);
- FreeAndNil(AIdHttp);
- PostStream.Free;
- Exit;
- end;
- end;
- PostStream.Free;
- FreeAndNil(AIdHttp);
- StrStream:=TStringStream.Create(ReponseData);
- AXMLDoc := TXMLDocument.Create(Application);
- AXMLDoc.Active := True;
- try
- AXMLDoc.LoadFromStream(StrStream);
- RootNode := AXMLDoc.DocumentElement;
- ChildNodes:=RootNode.ChildNodes;
- for i:=0 to ChildNodes.Count -1 do begin
- BodyNode := ChildNodes.Get(i);
- if UpperCase(BodyNode.NodeName) ='BODY' then begin
- BodyChildNode:=BodyNode.ChildNodes;
- if BodyChildNode.Count<>1 then begin
- EXIT;
- end;
- TempNode := BodyChildNode.Get(0);
- Result:= TempNode.NodeValue;
- end;
- end;
- except
- on Ex: Exception do
- begin
- ShowMessage('CA返回结果解析异常:'+ Ex.Message);
- StrStream.Free;
- AXMLDoc.Free;
- Exit;
- end;
- end;
- StrStream.Free;
- AXMLDoc.Free;
- end;
- function TJITAuth.Request: string;
- var
- JITVCTKObj:IJITVCTK;
- StrRandom, StrSignData:String;
- lErrorCode:Integer;
- ReponseData:String;
- StrStream:TStringStream;
- PostStream:TStringStream;
- RootNode:IXMLNode;
- HeadInfo:SHeadInfo;
- BodyInfo:SBodyInfo;
- I, iLoop:Integer;
- AConfig: ICAConfig;
- AIdHttp: TIdHTTP;
- AXMLDoc: TXMLDocument;
- begin
- //////////////////////////////////////////////////////////////////////////
- // 1. 生成认证请求报文
- //////////////////////////////////////////////////////////////////////////
- AConfig := GetCAConfig;
- JITVCTKObj:=CoJITVCTK.Create;
- lErrorCode:=JITVCTKObj.SetCert('SC', '', '', '', AConfig.GetCaSubject, '');
- if lErrorCode <> 0 then Exit;
- StrRandom := GenRandom;
- if StrRandom='' then Exit;
- StrSignData:=JITVCTKObj.AttachSignStr('', StrRandom);
- if StrSignData = '' then Exit;
-
- PostStream:=TStringStream.Create('');
- PostStream.WriteString('<?xml version="1.0" encoding="UTF-8"?>');
- PostStream.WriteString('<message>');
- PostStream.WriteString('<head>');
- PostStream.WriteString('<version>1.1</version>');
- PostStream.WriteString('<serviceType>AuthenService</serviceType>');
- PostStream.WriteString('</head>');
- PostStream.WriteString('<body>');
- PostStream.WriteString('<clientInfo>');
- PostStream.WriteString('<clientIP>'+ '192.168.1.100' +'</clientIP>');
- PostStream.WriteString('</clientInfo>');
- PostStream.WriteString('<appId>' + AConfig.GetAppID + '</appId>');
- PostStream.WriteString('<authen>');
- PostStream.WriteString('<authCredential authMode="cert">');
- PostStream.WriteString('<attach>' + StrSignData + '</attach>');
- PostStream.WriteString('</authCredential>');
- PostStream.WriteString('</authen>');
- PostStream.WriteString('<accessControl>true</accessControl>');
- PostStream.WriteString('<attributes attributeType="all">');
- PostStream.WriteString('<attr name="' + AnsiToUtf8('身份证') + '" namespace="http://www.jit.com.cn/ums/ns/user"></attr>');
- {
- PostStream.WriteString('<attr name="X509Certificate.SubjectDN" namespace="http://www.jit.com.cn/cinas/ias/ns/saml/saml11/X.509"></attr>');
- PostStream.WriteString('<attr name="UMS.UserID" namespace="http://www.jit.com.cn/pmi/pms/ns/role"></attr>');
- PostStream.WriteString('<attr name="' + AnsiToUtf8('性别') + '" namespace="http://www.jit.com.cn/ums/ns/user"></attr>');
- PostStream.WriteString('<attr name="' + AnsiToUtf8('职务') + '" namespace="http://www.jit.com.cn/ums/ns/user"></attr>');
- PostStream.WriteString('<attr name="' + AnsiToUtf8('部门') + '" namespace="http://www.jit.com.cn/ums/ns/user"></attr>');
- }
- PostStream.WriteString('</attributes>');
- PostStream.WriteString('</body>');
- PostStream.WriteString('</message>');
- //////////////////////////////////////////////////////////////////////////
- // 2. 发送认证请求报文
- //////////////////////////////////////////////////////////////////////////
- AIdHttp := TIdHTTP.Create(nil);
- InitRequestHead(AIdHttp);
- PostStream.Position := 0;
- try
- ReponseData := AIdHttp.Post(AConfig.GetURL, PostStream);
- except
- on Ex: Exception do
- begin
- ShowMessage('CA服务器可能不存在,详细错误:' + Ex.Message);
- FreeAndNil(AIdHttp);
- PostStream.Free;
- Exit;
- end;
- end;
- PostStream.Free;
- FreeAndNil(AIdHttp);
- /////////////////////////////////////////////////////////////////////////
- // 3. 解析服务器响应报文
- //////////////////////////////////////////////////////////////////////////
- StrStream:=TStringStream.Create(ReponseData);
- AXMLDoc := TXMLDocument.Create(Application);
- try
- AXMLDoc.LoadFromStream(StrStream);
- RootNode := AXMLDoc.DocumentElement;
- ParseRootNode(RootNode, HeadInfo, BodyInfo);
- except
- on Ex: Exception do
- begin
- ShowMessage('CA返回结果解析异常:'+ Ex.Message);
- StrStream.Free;
- AXMLDoc.Free;
- Exit;
- end;
- end;
- StrStream.Free;
- AXMLDoc.Free;
- Debug('版本:'+ HeadInfo.Version, 'TJITAuth.Request');
- Debug('服务类型:' + HeadInfo.ServiceType, 'TJITAuth.Request');
- Debug('认证结果:' + HeadInfo.AuthResult, 'TJITAuth.Request');
- Debug('错误码:' + HeadInfo.ErrorCode, 'TJITAuth.Request');
- Debug('错误信息:' + HeadInfo.ErrorDesc, 'TJITAuth.Request');
- Debug('认证模式:' + BodyInfo.AuthMode, 'TJITAuth.Request');
- Debug('认证结果:' + BodyInfo.AuthResult, 'TJITAuth.Request');
- Debug('访问控制:' + BodyInfo.AccessControlResult, 'TJITAuth.Request');
- if BodyInfo.AttrList <> nil then
- begin
- try
- for iLoop := 0 to BodyInfo.AttrList.Count - 1 do
- if SameText('X509Certificate.SubjectDN', BodyInfo.AttrList[iLoop]) then
- begin
- Result := RequestUserJsonBySubjectDN(BodyInfo.AttrList[iLoop + 2]);
- Break;
- end;
- finally
- BodyInfo.AttrList.Free;
- end;
- end;
- end;
- function TJITAuth.RequestUserJsonBySubjectDN(ASubjectDN: string): string;
- const
- GETUSER_URL: string = 'http://%s:%d/api/basic/GetUserByCA?appKey=%s&appSecret=%s&ca=%s';
- var
- AItems: TStrings;
- iLoop, jLoop: Integer;
- strTmp: string;
- AID: string;
- AIdHttp: TIdHttp;
- AppCentreConfig: IAppCentreConfig;
- AURL: string;
- begin
- AItems := SplitString(ASubjectDN, ',');
- try
- for iLoop := 0 to AItems.Count - 1 do
- begin
- strTmp := Trim(AItems[iLoop]);
- if Pos('T=', strTmp) = 1 then
- begin
- AID := Copy(StrTmp, 3, Length(StrTmp) - 2);
- Break;
- end;
- end;
- finally
- FreeAndNil(AItems);
- end;
- if AID = '' then
- Exit;
- AIdHttp := TIdHttp.Create(Application);
- try
- AppCentreConfig := GetAppCentreConfig;
- AURL := Format(GETUSER_URL,
- [Utf8ToAnsi(AppCentreConfig.GetIP),
- AppCentreConfig.GetPort,
- AppCentreConfig.GetLxtAppKey,
- AppCentreConfig.GetLxtAppSecret,
- AID]);
- Result := Utf8ToAnsi(AIdHttp.Get(AURL));
- finally
- FreeAndNil(AIdHttp);
- end;
- end;
- function TJITAuth.GetNodeAttributeValue(xmlNode:IXMLNode; strAttribute:String):String;
- begin
- // xmlNode.Get
- end;
- procedure TJITAuth.ParseHeadNode(HeadNode:IXMLNode; var HeadInfo: SHeadInfo);
- var
- ChildNodes:IXMLNodeList;
- ChildNode:IXMLNode;
- I:Integer;
- tempValue:String;
- begin
- ChildNodes:=HeadNode.GetChildNodes();
- for I:=0 to ChildNodes.Count-1 do begin
- ChildNode:=ChildNodes.Get(i);
- tempValue:=ChildNode.Text;
- if lowercase(ChildNode.NodeName)='version' then begin
- HeadInfo.Version := tempValue;
- end else if lowercase(ChildNode.NodeName)='servicetype' then begin
- HeadInfo.ServiceType := tempValue;
- end else if lowercase(ChildNode.NodeName)='messagestate' then begin
- HeadInfo.AuthResult := tempValue;
- end else if lowercase(ChildNode.NodeName)='messagecode' then begin
- HeadInfo.ErrorCode := tempValue;
- end else if lowercase(ChildNode.NodeName)='messagedesc' then begin
- HeadInfo.ErrorDesc := tempValue;
- end;
- end;
-
- end;
- procedure TJITAuth.ParseRootNode(RootNode:IXMLNode; var HeadInfo:SHeadInfo; var BodyInfo:SBodyInfo);
- var
- ChildNodes:IXMLNodeList;
- ChildNode:IXMLNode;
- I:Integer;
- begin
- ChildNodes:=RootNode.GetChildNodes();
- for I:=0 to ChildNodes.Count-1 do begin
- ChildNode:=ChildNodes.Get(I);
- if UpperCase(ChildNode.NodeName)='HEAD' then begin
- ParseHeadNode(ChildNode, HeadInfo);
- end else if UpperCase(ChildNode.NodeName)='BODY' then begin
- ParseBodyNode(ChildNode, BodyInfo);
- end;
- end;
-
- end;
- procedure TJITAuth.ParseBodyNode(BodyNode:IXMLNode; var BodyInfo: SBodyInfo);
- var
- ChildNodes:IXMLNodeList;
- ChildNode, AttribChildNode:IXMLNode;
- I,J:Integer;
- AuthChildNodes:IXMLNodeList;
- AttrName, AttrNameSpace, AttrValue:String;
- begin
- ChildNodes:=BodyNode.GetChildNodes();
- for I:=0 to ChildNodes.Count-1 do begin
- ChildNode:=ChildNodes.Get(I);
- if lowercase(ChildNode.NodeName)='authresultset' then begin
- AuthChildNodes:=ChildNode.ChildNodes;
- for J:=0 to AuthChildNodes.Count-1 do begin
- AttribChildNode:=AuthChildNodes.Get(J);
- if lowercase(AttribChildNode.NodeName)='authresult' then begin
- if AttribChildNode.HasAttribute('authMode') then BodyInfo.AuthMode:=AttribChildNode.Attributes['authMode'];
- if AttribChildNode.HasAttribute('success') then BodyInfo.AuthResult:=AttribChildNode.Attributes['success'];
- end;
- end;
- end else if lowercase(ChildNode.NodeName)='accesscontrolresult' then begin
- BodyInfo.AccessControlResult:=ChildNode.Text;
- end else if lowercase(ChildNode.NodeName)='attributes' then begin
- AuthChildNodes:=ChildNode.ChildNodes;
- BodyInfo.AttrList:=TStringList.Create;
- for J:=0 to AuthChildNodes.Count-1 do begin
- AttribChildNode:=AuthChildNodes.Get(J);
- if lowercase(AttribChildNode.NodeName)='attr' then begin
- if AttribChildNode.HasAttribute('name') then AttrName:=AttribChildNode.Attributes['name'];
- if AttribChildNode.HasAttribute('namespace') then AttrNameSpace:=AttribChildNode.Attributes['namespace'];
- AttrValue:=AttribChildNode.NodeValue;
- BodyInfo.AttrList.Add(AttrName);
- BodyInfo.AttrList.Add(AttrNameSpace);
- BodyInfo.AttrList.Add(AttrValue);
- end;
- end;
- end;
- end;
- end;
- end.
|