Web Service 'te SOAP Header nasıl kontrol edilir

C, C++ ve C++ Builder ile ilgili konuları buraya yazabilirsiniz.
Cevapla
leoeroz
Üye
Mesajlar: 6
Kayıt: 26 Eki 2017 10:35

Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen leoeroz »

Merhaba,
XE5 kullanıyorum; VCL Component 'leri kullanarak bir SOAP Sunucu hazırladım. Bir clinet uygulama hazırlayıp sunucunun WSDL dosyasını bu client 'a import ettim. Client ve Web Service sorunsuz çalıştı. Authendication için hem Service tarafında hem de Client tarafında TSOAPHeader 'dan türetilmiş bir Header class'ı hazırladım. Client tarafından bu Header'ı düzgün bir şekilde dolduruyor ve Service'e gönderebiliyorum. SOAP mesajını aşağıda görebilirsiniz.

Kod: Tümünü seç

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">

<SOAP-ENV:Header SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:NS1="urn:@:aaasdf">
	<NS1:MySOAPHeader xsi:type="NS1:MySOAPHeader">
		<Username xsi:type="xsd:string">deneme</Username>
		<Password xsi:type="xsd:string">test123</Password>
	</NS1:MySOAPHeader>
</SOAP-ENV:Header>

<SOAP-ENV:Body xmlns:NS2="urn:aaasdf-Iaaasdf" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<NS2:echoDouble><dValue xsi:type="xsd:double">12</dValue></NS2:echoDouble>
</SOAP-ENV:Body>

</SOAP-ENV:Envelope>
Service tarafına gelen bu Header'ı handle edip username ve password kontrolü yapmak istiyorum fakat yapamadım, çünkü Header a nasıl erişeceğimi anlayamadım. Bununla ilgili C++ da yapılmış bir örnek bulamadım, örnekler Delphi'de yapılmış hatta Embarcadero sitesinde bile C++ yok. Yardımcı olursanız çok sevinirim.
ismailkocacan
Üye
Mesajlar: 88
Kayıt: 25 Eyl 2011 06:11
Konum: İstanbul
İletişim:

Re: Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen ismailkocacan »

Buradaki dokümanda bulunan Delphi örneğini çevirmeyi deneyebilirsiniz.
http://docwiki.embarcadero.com/RADStudi ... AP_Headers

Kod: Tümünü seç

TServiceImpl.GetQuote(Symbol: string): Double;
var
  Headers: ISOAPHeaders;
  H: TAuthHeader;
begin
  Headers := Self as ISOAPHeaders;
  Headers.Get(AuthHeader, TSOAPHeader(H)); { Retrieve the authentication header }
  try
    if H = nil then
      raise ERemotableException.Create("SOAP header for authentication required");
    { code here to check name and password }
  finally
    H.Free;
  end;
  { now that user is authenticated, look up and return quote }
end;
TInvokableClass sınıfından miras alan, web methodlarınızı implement ettiğiniz sınıf içerisinde yakalayabilirsiniz.
Yazdığınız web servis ve client kodunu paylaşabilirseniz yardımcı olmaya çalışırım.
leoeroz
Üye
Mesajlar: 6
Kayıt: 26 Eki 2017 10:35

Re: Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen leoeroz »

Aslında ilk önce tarif ettiğiniz yere bakmıştım yukarıda belirttiğim gibi. Client tarafını bir şekilde c++ a çevirdim fakat servis tarafını çeviremedim.

Service:
.cpp

Kod: Tümünü seç

// ************************************************************************ //
// Implementation class for interface Iaaasdf
// ************************************************************************ //
#include <stdio.h>
#include <vcl.h>
#pragma hdrstop

#if !defined(__aaasdf_h__)
#include "aaasdf.h"
#endif

// ************************************************************************ //
// TaaasdfImpl implements interface Iaaasdf
// ************************************************************************ //
class TaaasdfImpl : public TInvokableClass, public Iaaasdf  {
public:
	/* Sample methods of Iaaasdf */
	SampleEnum echoEnum(SampleEnum eValue);
	TDoubleArray echoDoubleArray(const TDoubleArray daValue);
	TSampleStruct* echoStruct(const TSampleStruct* pStruct);
	double echoDouble(double dValue);

	/* IUnknown */
	HRESULT STDMETHODCALLTYPE QueryInterface(const GUID& IID, void **Obj) {
		return GetInterface(IID, Obj) ? S_OK : E_NOINTERFACE;
	}

	ULONG STDMETHODCALLTYPE AddRef() {
		return TInvokableClass::_AddRef();
	}

	ULONG STDMETHODCALLTYPE Release() {
		return TInvokableClass::_Release();
	}

	bool CheckHeader(){
              // ??
		return true;
	}

};


SampleEnum TaaasdfImpl::echoEnum(SampleEnum eValue) {
	/* TODO : Implement method echoEnum */
	return eValue;
}

TDoubleArray TaaasdfImpl::echoDoubleArray(TDoubleArray daValue) {
	/* TODO : Implement method echoDoubleArray */
	return daValue;
}

TSampleStruct* TaaasdfImpl::echoStruct(const TSampleStruct* pEmployee) {
	/* TODO : Implement method echoMyEmployee */
	return new TSampleStruct();
}

double TaaasdfImpl::echoDouble(const double dValue) {
	/* TODO : Implement method echoDouble */
	return dValue;
}

static void __fastcall aaasdfFactory(System::TObject* &obj) {
	static _di_Iaaasdf iInstance;
	static TaaasdfImpl *instance = 0;
	if (!instance) {
		instance = new TaaasdfImpl();
		instance->GetInterface(iInstance);
	}

	obj = instance;

	if(!instance->CheckHeader()){
		// ??
	}

}

// ************************************************************************ //
// The following routine registers the interface and implementation class
// as well as the type used by the methods of the interface
// ************************************************************************ //
static void RegTypes() {
	InvRegistry()->RegisterInterface(__delphirtti(Iaaasdf));
	InvRegistry()->RegisterInvokableClass(__classid(TaaasdfImpl), aaasdfFactory);
	InvRegistry()->RegisterHeaderClass(__delphirtti(Iaaasdf), __classid(MySOAPHeader));
}
#pragma startup RegTypes 32
.h

Kod: Tümünü seç

// ************************************************************************ //
// Invokable interface declaration header for aaasdf
// ************************************************************************ //
#ifndef   aaasdfH
#define   aaasdfH

#include <System.hpp>
#include <InvokeRegistry.hpp>
#include <XSBuiltIns.hpp>
#include <Types.hpp>

// ************************************************************************ //
// Enums exposed via SOAP must be byte-aligned
// ************************************************************************ //
#pragma option -b-

enum SampleEnum {
	etNone, etAFew, etSome, etALot
};
#pragma option -b.

// ************************************************************************ //
// To expose complex types via SOAP, the type must derive from TRemotable
// All published members of the type will be exposed.
// ************************************************************************ //
class TSampleStruct : public TRemotable {
private:
	AnsiString FLastName;
	AnsiString FFirstName;
	double FSalary;

__published:
	__property AnsiString LastName = {read = FLastName, write = FLastName};
	__property AnsiString FirstName = {read = FFirstName, write = FFirstName};
	__property double Salary = {read = FSalary, write = FSalary};
};

class MySOAPHeader : public TSOAPHeader {
private:
	UnicodeString FUsername;
	UnicodeString FPassword;

__published:
	__property UnicodeString Username = {read = FUsername, write = FUsername};
	__property UnicodeString Password = {read = FPassword, write = FPassword};
};

// ************************************************************************ //
// Remotable arrays must be Dynamic arrays since they must be discoverable
// at runtime.
// ************************************************************************ //
typedef DynamicArray<double>TDoubleArray;

// ************************************************************************ //
// Invokable interfaces must derive from IInvokable
// The methods of the interface will be exposed via SOAP
// ************************************************************************ //
__interface INTERFACE_UUID("{6D3639F4-DEB4-41D6-8E09-B3623B8232CA}") Iaaasdf : public IInvokable {
public:
	virtual SampleEnum echoEnum(SampleEnum eValue) = 0;
	virtual TDoubleArray echoDoubleArray(const TDoubleArray daValue) = 0;
	virtual TSampleStruct* echoStruct(const TSampleStruct* pEmployee) = 0;
	virtual double echoDouble(double dValue) = 0;
};
typedef DelphiInterface<Iaaasdf>_di_Iaaasdf;

#endif // aaasdfH
// ---------------------------------------------------------------------------
Client tarafında bir problemim yok diye düşünüyorum. Servise gönderdiğim SOAP mesajını loglayıp kontrol ettim, hatta önceki mesajımda paylaşmıştım SOAP Envelop'u. Yine de client kodunu aşağıda paylaşıyorum.

Client:
.cpp

Kod: Tümünü seç

// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl
//  >Import : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl>0
//  >Import : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl>1
//  >Import : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl>2
// Version  : 1.0
// (25.10.2017 20:28:26 - - $Rev: 56641 $)
// ************************************************************************ //

#include <System.hpp>
#pragma hdrstop

#if !defined(IaaasdfH)
#include "Iaaasdf.h"
#endif



namespace NS_Iaaasdf {

_di_Iaaasdf GetIaaasdf(bool useWSDL, System::String addr, Soaphttpclient::THTTPRIO* HTTPRIO)
{
  static const char* defWSDL= "D:\\PROJELER\\MyC++\\trainer\\65 ws client auth\\Iaaasdf.wsdl";
  static const char* defURL = "http://localhost:8080/soap/Iaaasdf";
  static const char* defSvc = "Iaaasdfservice";
  static const char* defPrt = "IaaasdfPort";
  if (addr=="")
    addr = useWSDL ? defWSDL : defURL;
  Soaphttpclient::THTTPRIO* rio = HTTPRIO ? HTTPRIO : new Soaphttpclient::THTTPRIO(0);
  if (useWSDL) {
    rio->WSDLLocation = addr;
    rio->Service = defSvc;
	rio->Port = defPrt;

	MySOAPHeader *hdr = new MySOAPHeader();
	hdr->Username = "deneme";
	hdr->Password = "test123";

	rio->SOAPHeaders->Send(hdr);

  } else {
    rio->URL = addr;
  }
  _di_Iaaasdf service;
  rio->QueryInterface(service);
  if (!service && !HTTPRIO)
    delete rio;
  return service;
}


// ************************************************************************ //
// This routine registers the interfaces and types exposed by the WebService.
// ************************************************************************ //
static void RegTypes()
{
  /* Iaaasdf */
  InvRegistry()->RegisterInterface(__delphirtti(Iaaasdf), L"urn:aaasdf-Iaaasdf", L"");
  InvRegistry()->RegisterDefaultSOAPAction(__delphirtti(Iaaasdf), L"urn:aaasdf-Iaaasdf#%operationName%");
  /* Iaaasdf->echoEnum */
  InvRegistry()->RegisterParamInfo(__delphirtti(Iaaasdf), "echoEnum", "return_", L"return", L"");
  /* Iaaasdf->echoDoubleArray */
  InvRegistry()->RegisterParamInfo(__delphirtti(Iaaasdf), "echoDoubleArray", "return_", L"return", L"");
  /* Iaaasdf->echoStruct */
  InvRegistry()->RegisterParamInfo(__delphirtti(Iaaasdf), "echoStruct", "return_", L"return", L"");
  /* Iaaasdf->echoDouble */
  InvRegistry()->RegisterParamInfo(__delphirtti(Iaaasdf), "echoDouble", "return_", L"return", L"");
  /* MySOAPHeader */
  RemClassRegistry()->RegisterXSClass(__classid(MySOAPHeader), L"urn:@:aaasdf", L"MySOAPHeader");
  /* SampleEnum */
  RemClassRegistry()->RegisterXSInfo(GetClsMemberTypeInfo(__typeinfo(SampleEnum_TypeInfoHolder)), L"urn:aaasdf", L"SampleEnum");
  /* TSampleStruct */
  RemClassRegistry()->RegisterXSClass(__classid(TSampleStruct), L"urn:@:aaasdf", L"TSampleStruct");
}
#pragma startup RegTypes 32

};     // NS_Iaaasdf
.h

Kod: Tümünü seç

// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl
//  >Import : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl>0
//  >Import : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl>1
//  >Import : D:\PROJELER\MyC++\trainer\65 ws client auth\Iaaasdf.wsdl>2
// Version  : 1.0
// (25.10.2017 20:28:26 - - $Rev: 56641 $)
// ************************************************************************ //

#ifndef   IaaasdfH
#define   IaaasdfH

#include <System.hpp>
#include <InvokeRegistry.hpp>
#include <XSBuiltIns.hpp>
#include <SOAPHTTPClient.hpp>

#if !defined(SOAP_REMOTABLE_CLASS)
#define SOAP_REMOTABLE_CLASS __declspec(delphiclass)
#endif

namespace NS_Iaaasdf {

// ************************************************************************ //
// The following types, referred to in the WSDL document are not being represented
// in this file. They are either aliases[@] of other types represented or were referred
// to but never[!] declared in the document. The types from the latter category
// typically map to predefined/known XML or Embarcadero types; however, they could also 
// indicate incorrect WSDL documents that failed to declare or import a schema type.
// ************************************************************************ //
// !:string          - "http://www.w3.org/2001/XMLSchema"[Gbl]
// !:double          - "http://www.w3.org/2001/XMLSchema"[Gbl]
// !:TDoubleDynArray - "http://www.borland.com/namespaces/Types"[GblCplx]

class SOAP_REMOTABLE_CLASS MySOAPHeader;
class SOAP_REMOTABLE_CLASS TSampleStruct;

enum class SampleEnum   /* "urn:aaasdf"[GblSmpl] */
{
  etNone, 
  etAFew, 
  etSome, 
  etALot
};

class SampleEnum_TypeInfoHolder : public TObject {
  SampleEnum __instanceType;
public:
__published:
  __property SampleEnum __propType = { read=__instanceType };
};



// ************************************************************************ //
// XML       : MySOAPHeader, global, <complexType>
// Namespace : urn:@:aaasdf
// Info      : Header
// ************************************************************************ //
class MySOAPHeader : public TSOAPHeader {
private:
  UnicodeString   FUsername;
  UnicodeString   FPassword;
__published:
  __property UnicodeString   Username = { read=FUsername, write=FUsername };
  __property UnicodeString   Password = { read=FPassword, write=FPassword };
};




// ************************************************************************ //
// XML       : TSampleStruct, global, <complexType>
// Namespace : urn:@:aaasdf
// ************************************************************************ //
class TSampleStruct : public TRemotable {
private:
  UnicodeString   FLastName;
  UnicodeString   FFirstName;
  double          FSalary;
__published:
  __property UnicodeString   LastName = { read=FLastName, write=FLastName };
  __property UnicodeString  FirstName = { read=FFirstName, write=FFirstName };
  __property double         Salary = { read=FSalary, write=FSalary };
};



// ************************************************************************ //
// Namespace : urn:aaasdf-Iaaasdf
// soapAction: urn:aaasdf-Iaaasdf#%operationName%
// transport : http://schemas.xmlsoap.org/soap/http
// style     : rpc
// use       : encoded
// binding   : Iaaasdfbinding
// service   : Iaaasdfservice
// port      : IaaasdfPort
// URL       : http://localhost:8080/soap/Iaaasdf
// ************************************************************************ //
__interface INTERFACE_UUID("{819FEDBA-8C1C-2AAB-5953-DD7A44D3C033}") Iaaasdf : public IInvokable
{
public:

    // Headers: MySOAPHeader:pInOut
  virtual SampleEnum      echoEnum(const SampleEnum eValue) = 0; 

    // Headers: MySOAPHeader:pInOut
  virtual TDoubleDynArray echoDoubleArray(const TDoubleDynArray daValue) = 0; 

    // Headers: MySOAPHeader:pInOut
  virtual TSampleStruct*  echoStruct(const TSampleStruct* pEmployee) = 0; 

    // Headers: MySOAPHeader:pInOut
  virtual double          echoDouble(const double dValue) = 0; 
};
typedef DelphiInterface<Iaaasdf> _di_Iaaasdf;

_di_Iaaasdf GetIaaasdf(bool useWSDL=false, System::String addr= System::String(), Soaphttpclient::THTTPRIO* HTTPRIO=0);


};     // NS_Iaaasdf

#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using  namespace NS_Iaaasdf;
#endif

#endif // IaaasdfH
Teşekkürler
ismailkocacan
Üye
Mesajlar: 88
Kayıt: 25 Eyl 2011 06:11
Konum: İstanbul
İletişim:

Re: Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen ismailkocacan »

ISOAPHeaders.Get

MyService.h

Kod: Tümünü seç

// ************************************************************************ //
// Invokable interface declaration header for MyService
// ************************************************************************ //
#ifndef   MyServiceH
#define   MyServiceH

#include <System.hpp>
#include <Soap.InvokeRegistry.hpp>
#include <Soap.XSBuiltIns.hpp>
#include <System.Types.hpp>

class MySOAPHeader : public TSOAPHeader
{
private:
	UnicodeString FUsername;
	UnicodeString FPassword;

__published:
	__property UnicodeString Username = {read = FUsername, write = FUsername};
	__property UnicodeString Password = {read = FPassword, write = FPassword};
};

// ************************************************************************ //
//  Invokable interfaces must derive from IInvokable
//  The methods of the interface will be exposed via SOAP
// ************************************************************************ //
__interface INTERFACE_UUID("{3904E8E3-6D1A-488D-A25D-69E00D45BFBB}") IMyService : public IInvokable
{
public:
  virtual int BirSeylerYap() = 0;
};
typedef DelphiInterface<IMyService> _di_IMyService;


#endif // MyServiceH
//---------------------------------------------------------------------------
MyService.cpp

Kod: Tümünü seç

// ************************************************************************ //
// Implementation class for interface IMyService
// ************************************************************************ //
#include <stdio.h>
#include <vcl.h>
#pragma hdrstop

#if !defined(__MyService_h__)
#include "MyService.h"
#endif

// ************************************************************************ //
//  TMyServiceImpl implements interface IMyService
// ************************************************************************ //
class TMyServiceImpl : public TInvokableClass, public IMyService
{
public:
  int BirSeylerYap();

  /* IUnknown */
  HRESULT STDMETHODCALLTYPE QueryInterface(const GUID& IID, void **Obj)
						{ return GetInterface(IID, Obj) ? S_OK : E_NOINTERFACE; }
  ULONG STDMETHODCALLTYPE AddRef() { return TInvokableClass::_AddRef();  }
  ULONG STDMETHODCALLTYPE Release() { return TInvokableClass::_Release();  }
};

int TMyServiceImpl::BirSeylerYap()
{
   MySOAPHeader* mySoapHeader = new MySOAPHeader();
   TSOAPHeader* soapHeader;

   soapHeader = FSOAPHeaders->Get(mySoapHeader->ClassType());
   mySoapHeader = (MySOAPHeader*)soapHeader;

   String userName = mySoapHeader->Username;
   String password = mySoapHeader->Password;

   delete mySoapHeader;

   return 31;
}


static void __fastcall MyServiceFactory(System::TObject* &obj)
{
  static _di_IMyService iInstance;
  static TMyServiceImpl *instance = 0;
  if (!instance)
  {
    instance = new TMyServiceImpl();
    instance->GetInterface(iInstance);
  }
  obj = instance;
}

// ************************************************************************ //
//  The following routine registers the interface and implementation class
// ************************************************************************ //
static void RegTypes()
{
  InvRegistry()->RegisterInterface(__delphirtti(IMyService));
  InvRegistry()->RegisterHeaderClass(__delphirtti(IMyService), __classid(MySOAPHeader));
  InvRegistry()->RegisterInvokableClass(__classid(TMyServiceImpl), MyServiceFactory);
}
#pragma startup RegTypes 32

GetSoapHeader.zip
SoapHeader
(119.66 KiB) 368 kere indirildi
leoeroz
Üye
Mesajlar: 6
Kayıt: 26 Eki 2017 10:35

Re: Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen leoeroz »

ismailkocacan yardımlarınız için çok teşekkür ederim.

Zip te gönderdiğiniz projeyi XE5 te derlemeye çalıştım. Client sorunsuz derlendi fakat servis derleme aşamasında soapserver.bpi dosyasının import edilmesini istedi. Bu dosyayı bulamadım, ..Rad Studio../lib/.. altında soaprtl.bpi dosyasını bulup import ettim fakat işe yaramadı. Yönteminizi inceleyerek yeni bir proje oluşturup derleyip çalıştırabildim fakat client tan service e request attığımda bu sefer de ERemotableException hatası aldım. Service'i debug ettim, FSOAPHeaders->Get(mySoapHeader->ClassType()); bu işlem yapılıyorken Access violation oluşuyor. Bir fikriniz var mıdır? FSOAPHeaders NULL mı öncesinde bir instance almak gerekiyormu emin olamadım.
Dosya ekleri
uygulamalar.zip
(101.98 KiB) 419 kere indirildi
log.zip
(39.3 KiB) 387 kere indirildi
ismailkocacan
Üye
Mesajlar: 88
Kayıt: 25 Eyl 2011 06:11
Konum: İstanbul
İletişim:

Re: Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen ismailkocacan »

Projeyi Berlin'de yaptım.Test ettiğimde bilgiler servise düzgün geliyordu.
instance alınmasına gerek olmaması lazım.Zaten gelen request ile otomatik oluşması gerekir diye düşünüyorum.
Deneyip bakmak lazım.
Service tarafında MySOAPHeader(TRemotable) tip bilgilerinin register edildiği kısımı kontrol edebilirsiniz belki...

Kod: Tümünü seç

InvRegistry()->RegisterHeaderClass(__delphirtti(IMyService), __classid(MySOAPHeader));
leoeroz
Üye
Mesajlar: 6
Kayıt: 26 Eki 2017 10:35

Re: Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen leoeroz »

XE8'de denedim çalıştı yöntemde bir problem yokmuş fakat aynı kod XE5'te derlenince "Access violation at address 519487F8 in module 'soaprtl190.bpl'. Read of address 00000004" hatası oluşuyor malesef.

Tekrar çok teşekkürler ismailkocacan.
ismailkocacan
Üye
Mesajlar: 88
Kayıt: 25 Eyl 2011 06:11
Konum: İstanbul
İletişim:

Re: Web Service 'te SOAP Header nasıl kontrol edilir

Mesaj gönderen ismailkocacan »

Rica ederim kolay gelsin.
Cevapla