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 := ''
+ ''
+ ''
+ '1.0'
+ 'OriginalService'
+ ''
+ ''
+ '' + AConfig.GetAppID + ''
+ ''
+ '';
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('');
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('1.1');
PostStream.WriteString('AuthenService');
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString(''+ '192.168.1.100' +'');
PostStream.WriteString('');
PostStream.WriteString('' + AConfig.GetAppID + '');
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('' + StrSignData + '');
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('true');
PostStream.WriteString('');
PostStream.WriteString('');
{
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('');
}
PostStream.WriteString('');
PostStream.WriteString('');
PostStream.WriteString('');
//////////////////////////////////////////////////////////////////////////
// 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.