Fasil Hayat's blog

...C#, .Net, Sharepoint, BizTalk, JQuery...

SOAP beskeder består af et 'MessageBody' og et 'MessageHeader' segment, hvor man typisk i 'MessageBody' segmentet udveksler forretningsdata, kan man benytte sig af SOAP header til udveksling af sekundære data. Det kan være data, der altid skal sendes med over via SOAP headeren fx. den kaldende parts autorisations data.

Her er et simpelt eksempel på, hvordan man kan berige data udvekslingen med en SOAP header fra en klient, som bagefter kan udvindes hos service udbyderen.

Kontrakter:

   1:  namespace MitNamespace.Foo {
   2:      public class MinMessageHeader{
   3:          public string BrugerId { get; set; }
   4:          public string ApplikationId { get; set; }
   5:      }
   6:  }
   7:   
   8:  namespace MitNamespace.Foo {
   9:      public class HentEtEllerAndetRequest {
  10:          public MessageHeader<MinMessageHeader> Header { get; set; }
  11:          public string EnForretningsId { get; set; }
  12:      }
  13:  }


Klient kode:

   1:  var klient = new MinProxy.MinServiceClient();
   2:   
   3:  using (var scope = new OperationContextScope(klient.InnerChannel)) {
   4:      var req = new HentEtEllerAndetRequest();
   5:      req.EnforretningsId = "25";
   6:      req.Header = new MessageHeader<MinMessageHeader>(new MinMessageHeader {
   7:                      BrugerId = "FHA", 
   8:                      ApplikationId = "NavnPaaApplikation", 
   9:                  });
  10:      var messageHeader = req.Header;
  11:      var header = messageHeader.GetUntypedHeader("MinCustomHeader", 
  12:                                          "http://www.fasil.dk/Applikation");
  13:      OperationContext.Current.OutgoingMessageHeaders.Add(header);
  14:      var result = klient.HentNogleData(req);
  15:  }


Serverkode:

   1:  [OperationContract]
   2:  public HentNogleDataResponse HentNogleData(HentEtEllerAndetRequest request) {
   3:      MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
   4:      var headerData = headers.GetHeader<MinMessageHeader>("MinCustomHeader", 
   5:                                          "http://www.fasil.dk/Applikation");
   6:      ...
   7:      ...
   8:      ...
   9:  }


Man kan også benytte sig af data kontrakter istedet. Dette eksempel virker dog helt ubeklageligt. 
Klient koden kan naturligvis bestå af en 'abstract' klasse, hvor header oplysningerne sættes. Alle andre service kaldende klasser skal herefter implementere / nedarve fra denne 'abstract' klasse.

På server delen kan man naturligvis tjekke for headerdelen, inden et response sendes tilbage til klienten. Alternativt sendes en autentificerings- / autorisationsfejl tilbage til klienten, hvis header oplysningerne ikke er gyldige.



Mine to seneste indlæg har beskrevet, hvordan man kan opnå sikkerhed mellem en WCF service host og en service konsumerende klient. Spørgsmålet er, hvilken sikkerhedsløsning egner sig bedst. Nøjagtigt ligesom mange andre tekniske overvejelser findes der ikke ét endegyldigt svar. Der findes kun en vægtning, der er baseret på forskellige scenarier, og hvor om det gælder at finde den bedst egnede løsning.

Løsningsmodellen med to X.509 certifikater, nemlig et klient certifikat og et server certifikat, vil umiddelbart være den mest sikre. Fx. forsikrer den, hvis en tredje part skulle komme i besiddelse af et af certifikaterne, ikke kan udnytte dette til at få utilsigtet adgang, da man mangler det andet certifikat. Dog vil denne løsningsmodel kræve mere administration af certifikaterne, da alle klienter har deres eget dedikeret certifikat, der skal administreres og indregistreres på WCF serveren.

Løsning1

Løsningsmodellen med et enkelt certifikat letter denne administrations byrde, men sænker samtidigt sikkerheds niveauet en anelse, da hvis en tredje part skulle komme i besiddelse af certfikatet, kan bruge dette til at tilkendegive sig selv og få utilsigtet adgang til serveren. Der er dog naturligvis andre sikkerheds foranstaltninger, der forhindrer denne fremmede indtrængen.

Løsning2

Begge er dog en god og hurtig måde at få implementeret WCF message sikkerhed på.

Er der et ønske om at kryptere kommunikationen mellem service klient og service host, kan man signere data trafikken med certifikaterne. Kommunikationen vil herefter ske over HTTPS istedet for HTTP protokollen.
Der vil være et indlæg, der behandler dette emne på et senere tidspunkt.



Det forrige indlæg handlede om at gøre brug af to X.509 certifikater til implementering af WCF message sikkerhed. Nemlig et klient certifikat og et server certifikat. Dette indlæg kommer til at handle om at gøre brug af et enkelt fælles certifikat. Har man ikke lyst til at rode rundt med for mange certifikater, kan denne løsning benyttes. Konfiguration og fremgangsmåden minder meget om det forrige indlæg, dog er der et lille trick ved eksport af X.509 certifikatet, der vil blive beskrevet senere.

Vi starter med at danne et fælles certifikat, dette kan gøres på WCF service host maskinen:

makecert -pe -ss My -sr LocalMachine -a sha1 -sky exchange -n CN=Common

Tryk 'Start' -> Kør 'mmc'

Dette vil starte et konsol vindue, og for at se certifikatet skal man gøre følgende:
Tryk på 'File' -> 'Add/Remove Snap-in...' vælge 'Certificates' under 'Available snap-ins' og trykke på 'Add' -> 'Computer account' -> Next -> Finnish

mmc konsol

Under 'Personal/Certificates' vil man finde certifikatet. Herefter skal "NETWORK SERVICE" tildeles læse rettigheder for at læse den private nøgle på certifikatet.
Højreklik på 'Common' certifikatet -> All Tasks -> 'Manage Private Keys...'.
Herefter gives "NETWORK SERVICE" Full control. Højreklik herefter på 'Common' certifikatet og vælg 'Copy'. Find 'Trusted people\Certificates' og kopier certifikatet herunder.

Certifikatet skal herefter eksporteres. Dette gøres på følgende måde:

Højreklik på 'MyServer' certifikatet -> All Tasks -> Export -> Next -> Vælg 'Yes, export the private key' -> 'Personal Information Exchange - PKCS #12 (.PFX)' -> Next -> Angive et kodeord -> Next -> 'Common' og gem certifikatet.

Kopier herefter certifikatet over på klient maskinen, så den er klar til senere brug.

Nu skal den maskine, der udstiller WCF service konfigureres.

I web.config filen skal følgende konfiguration sættes op.
Web.config filen udvides med konfiguration af certifikat delen:

Efterfølgende sættes klient maskinen op. Først skal 'Common' certifikatet fra tidligere importeres. Dette gøres ved at starte MMC på samme måde som før og tilføje certificates snap-in, 'Computer Account' og herefter højreklikke på 'Personal' -> All Task og vælge import. Højreklik herefter på 'Common' certifikatet og vælg 'Copy'. Find 'Trusted people\Certificates' og kopier certifikatet herunder.

Tildel "NETWORK SERVICE" læse rettigheder på samme måde som før.

Trick!
Eksportér 'Common' certifikatet på følgende måde:
Højreklik på 'Common' certifikatet -> All Tasks -> Export -> Next -> Vælg 'No, do not export the private key' -> Base-64 encoded X.509(.CER) -> 'MyServer' og gem certifikatet. Importér 'Common' certifikatet igen. Dette vil erstatte *.pfx certifikatet med *.cer versionen.

Nu sættes klientens web.config op.

Test applikationen...og det hele burde spille fint uden problemer.

WCF sikkerheds autentificering af klient og server vha. et enkelt X.509 certifikat.



Til implementering af sikkerhed mellem servicehost og klient, kan man benytte sig af X.509 certifikater. Der findes to måder, hvorpå denne sikkerhed kan opnås. Der kan enten benyttes af:

  1. Et dedikeret server certifikat og et klient certifikat til autentificering.
  2. Et enkelt certifikat til autentificering af både servicehost og klient.


Dette indlæg kommer til at handle om server og klient -certifikat autentificering.

Det er forudsat, man allerede har en WCF service kørende, der udstiller forskellige services til en serviceklient. I dette eksempel benyttes to seperate maskiner, der er medlem af samme domæne, dog er dette ikke noget krav. På den ene maskine (service host) udstiller en WCF service, og den anden maskine (service klient) konsumerer denne service. Har man allerede denne konstellation, er resten lidt konfiguration og lidt certifikat gymnastik.

Lad os starte med at danne certifikaterne, og her starter vi med at danne et WCF Server certifikat.
Vi benytter os af 'makecert.exe' command-line utility på den maskine, hvor vi har en WCF service kørende. Start en cmd prompt op og kør følgende kommando:

makecert -pe -ss My -sr LocalMachine -a sha1 -sky exchange -n CN=MyServer

Dette vil danne et certifkat og registrere det på den lokale maskine under 'Personal'. Udover dette er det mest væsentlige -pe, der sørger for, man kan eksportere certifikatet, hvilket skal gøres i forbindelse med klient autentificeringen. For at se om certifikatet er korrekt installeret på maskinen, kan mmc startes på følgende måde:

Tryk 'Start' -> Kør 'mmc'

Dette vil starte et konsol vindue, og for at se certifikatet skal man gøre følgende:

Tryk på 'File' -> 'Add/Remove Snap-in...' vælge 'Certificates' under 'Available snap-ins' og trykke på 'Add' -> 'Computer account' -> Next -> Finnish

Under 'Personal/Certificates' vil man finde certifikatet. Herefter skal "NETWORK SERVICE" tildeles læse rettigheder for at læse den private nøgle på certifikatet. 

Højreklik på 'MyServer' -> All Tasks -> 'Manage Private Keys...'.
Herefter gives "NETWORK SERVICE" Full control.

Certifikatet skal herefter eksporteres. Dette gøres på følgende måde:

Højreklik på 'MyServer' certifikatet -> All Tasks -> Export -> Next -> Vælg 'No, do not export the private key' -> Base-64 encoded X.509(.CER) -> 'MyServer' og gem certifikatet.

Kopier herefter certifikatet over på klient maskinen, så den er klar til senere brug.

Nu skal den maskine, der udstiller WCF service konfigureres.
I web.config filen skal følgende konfiguration sættes op:

serverconfig

Det der er værd at bemærke, er den del af konfigurationen, der beskriver serviceCredentials forbereder den kaldende part til at autentificere sig mod WCF serveren. Da disse certifikater ikke er udstedt af en betroet autoritet som fx. VeriSign, men er derimod selvskabte certifikater, sættes CertificationValidationMode til 'PeerTrust'. På denne måde angives, at certifikatet er 'self-issued' og kan bruges pålideligt imellem parterne.

Efterfølgende sættes klient maskinen op. Først skal 'MyServer' certifikatet fra tidligere importeres. Dette gøres ved at starte MMC på samme måde som før og tilføje certificates snap-in, 'Computer Account' og herefter højreklikke på 'Personal' -> All Task og vælge import. Højreklik herefter på 'MyServer' certifikatet og vælg 'Copy'. Find 'Trusted people\Certificates' og kopier certifikatet herunder.
Nu skal vi lave et klient certifikat, som skal bruges på serveren til at identificere klienten. Start en cmd prompt og kør følgende kommando:

makecert -pe -ss My -sr LocalMachine -a sha1 -sky exchange -n CN=MyClient

Tjek efter om certifikatet er kommet rigtigt ind under '
Personal\Certificates'.

Tildel "NETWORK SERVICE" læse rettigheder på samme måde som før. Eksportér herefter certifikatet efter samme fremgangsmåde som tidligere, og gem det på WCF serveren, så certifikatet er klar til senere import.

Nu sættes klientens web.config op.

clientconfig

Gå tilbage til WCF maskinen og importer 'MyClient' certifikatet, og kopier herefter certifikatet under 'Trusted People\Certicates'.

Test applikationen...og det hele burde spille fint uden problemer.

WCF sikkerheds autentificering af klient og server vha. X.509 certifikater.



Fasil Malik Hayat

Developer
.Net, WCF, Sharepoint, MOSS, Biztalk, JQuery.

linkedin facebook twitter plaxo google+ grooveshark boxee
fasil

Education

fasil

Bachelor of Science (Honours)
De Montfort University, Leicester.

Fag: Java, MVC, Information Strategy, ITIL

Microsoft Certified Technology Specialist

Skills

.net vs2010 - C# sharepoint sql server jquery ubuntu java netbeans


  

Sign in