Ver Mensaje Individual
  #3  
Antiguo 14-11-2024
javipes javipes is offline
Miembro
 
Registrado: jul 2007
Posts: 25
Reputación: 0
javipes Va por buen camino
Yo con el tema de certificados, lo que hago es cargarlos desde el almacen de certificados sobre una lista que luego asigno a los items de un combobox para poder seleccionar el certificado que usaré en el envio:
Código Delphi [-]
function Certificados(ListaCertificados: TStringList): Integer;
var
  hStore: HCERTSTORE;
  PrevContext, CurContext: PCERT_CONTEXT;
  cbSize: DWORD;
  sNombre: String;
begin
  // Devuelve un StringList con los certificados instalados en el equipo
  ListaCertificados.Clear;

  hStore := CertOpenSystemStore(0, PChar('MY'));
  if Assigned(hStore) then
  begin
    PrevContext := nil;
    CurContext := CertEnumCertificatesInStore(hStore, PrevContext);
    while Assigned(CurContext) do
    begin
      sNombre := '';
      cbSize := CertGetNameString(CurContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
        nil, nil, 0);
      if cbSize > 0 then
      begin
        SetLength(sNombre, cbSize - 1);
        CertGetNameString(CurContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil,
          PChar(sNombre), cbSize);
        ListaCertificados.Add(sNombre);
      end;

      PrevContext := CurContext;
      CurContext := CertEnumCertificatesInStore(hStore, PrevContext);
    end;
  end;

  Result := ListaCertificados.Count;
end;


para cargar los certificados en un combo (cmbCertificados:TComboBox; //en el form )



Código Delphi [-]
var indice:integer; lisCert:TStringList;
begin
   //CargaCertificados;
   lisCert:=nil;
   indice:=DMEnvioLAF.CargaCertificados(lisCert);
   cmbcertificados.Clear;
   cmbCertificados.Items.AddStrings(lisCert);
   lisCert.free;
....


y cuando se selecciona un certificado del combo se deja en una variable infoCertificado:string; el contenido del combo, el elemento seleccionado


y es en el evento OnbeforePost del componente HTTPRIO donde asigno el certificado a partir de ese infocertificado.
Esto plantea un problema en delphi10 y en delphi11 porque la declaracion de tipos es distinta y en delphi11 se accede directamente para asignar los datos del certificado:


Código Delphi [-]
procedure TDMEnvioLAF.HTTPRIOENVHTTPWebNode1BeforePost(
  const HTTPReqResp: THTTPReqResp; Client: THTTPClient); //delphi11
//  const HTTPReqResp: THTTPReqResp; Data: Pointer);       delphi10

var  Store : IStore;
     Certs : ICertificates;
     Cert : ICertificate2;
     V : OleVariant;
{$REGION 'delphi10 var'}
//delphi10-------------------------------------------------------- ini
//     CertContext : ICertContext;
//     PCertContext : PCCERT_CONTEXT;
//     lasterror:cardinal; Buffer: array[0..255] of Char;
// const
//     INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;
//delphi10 ------------------------------------------------------- fin
{$ENDREGION 'delphi10 var'}
begin
     V := infoCertificado;

     Store := CoStore.Create;
     Store.Open(CAPICOM_CURRENT_USER_STORE, 'MY',CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED );
     Certs := Store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME,V,False );

     if Certs.Count > 0 then
       begin
         Cert:=IInterface(Certs.Item[1]) as ICertificate2;
         {$REGION 'delphi10 code'}
//delphi10-------------------------------------------------------- ini
//         CertContext:=Cert as ICertContext;
//         CertContext.Get_CertContext(Integer(PCertContext));
//         if InternetSetOption(Data,INTERNET_OPTION_CLIENT_CERT_CONTEXT,PCertContext,Sizeof(CERT_CONTEXT)) = False then
//           begin
//            lasterror:=GetLastError;
//            FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, LastError, 0, @Buffer, SizeOf(Buffer), nil);
//             showmessage('ERROR ('+inttostr(lasterror)+') asignando certificado'#13+Buffer);
//           end
//delphi10 ------------------------------------------------------- fin
         {$ENDREGION 'delphi10 code'}
//delphi11................................................................ini
        with HTTPRIOENV.HTTPWebNode.ClientCertificate do
          begin
          CertName:=V;
            SerialNum:=cert.serialnumber;
          end
//delphi11...............................................................fin
       end
     else
        showmessage('ERROR localizando certificado');
end;
no asigno la password, cojo el certificado directamente del almacen; no sé si al usarlo desde alli necesito informar la password. Pero a mi me funciona


ah, se necesita usar la libreria CAPICOM_TLB y tambien System.Net.HttpClient, System.Net.HttpClientComponent, Soap.Rio,
Soap.SOAPHTTPClient, Soap.SOAPHTTPTrans, soap.win.certhelper

puede que haya alguna de más, pero yo las tengo todas ellas puestas
Responder Con Cita