Skip to content

Instantly share code, notes, and snippets.

@nunorelvao
Forked from donelodes/ATSecurityHeader.vb
Last active August 29, 2015 14:11
Show Gist options
  • Save nunorelvao/938e8d8834795c0cca5c to your computer and use it in GitHub Desktop.
Save nunorelvao/938e8d8834795c0cca5c to your computer and use it in GitHub Desktop.
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Dispatcher
Imports System.ServiceModel
Public Class AddHeadersMessageInspector
Implements IClientMessageInspector
Public Property Headers As MessageHeader()
Public Sub New(ParamArray headers As MessageHeader())
Me.Headers = headers
End Sub
Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements System.ServiceModel.Dispatcher.IClientMessageInspector.BeforeSendRequest
If Headers IsNot Nothing Then
For i = Headers.Length - 1 To 0 Step -1
request.Headers.Insert(0, Headers(i))
Next
End If
Return request
End Function
Public Sub AfterReceiveReply(ByRef reply As Message, correlationState As Object) Implements System.ServiceModel.Dispatcher.IClientMessageInspector.AfterReceiveReply
End Sub
End Class
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="ATPublicKeyPath" value="c:\ChavePublicaAT.cer"/>
</appSettings>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AddClientCertificateBehaviour">
<clientCredentials>
<clientCertificate x509FindType="FindBySubjectName" storeName="My" storeLocation="CurrentUser" findValue="Testes Web Services"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="documentosTransporteSOAP" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://servicos.portaldasfinancas.gov.pt:701/sgdtws/documentosTransporte" binding="basicHttpBinding" bindingConfiguration="documentosTransporteSOAP" contract="ATTransportServiceReference.documentosTransporte" name="documentosTransporteSOAP" behaviorConfiguration="AddClientCertificateBehaviour">
</endpoint>
</client>
</system.serviceModel>
</configuration>
Imports System.ServiceModel.Channels
Imports System.ServiceModel
Imports System.Xml
Imports System.Security.Cryptography
Imports System.IO
Imports System.Security.Cryptography.X509Certificates
Public Class ATSecurityHeader
Inherits MessageHeader
Public Property UserName As String
Public Property Password As String
Public Property Certificate As X509Certificate2
Public Overrides ReadOnly Property Name As String
Get
Return "Security"
End Get
End Property
Public Overrides ReadOnly Property [Namespace] As String
Get
Return "http://schemas.xmlsoap.org/ws/2002/12/secext"
End Get
End Property
Public Overrides ReadOnly Property MustUnderstand As Boolean
Get
Return False
End Get
End Property
Public Sub New(userName As String, password As String, certificate As X509Certificate2)
Me.UserName = userName
Me.Password = password
Me.Certificate = certificate
End Sub
Protected Overrides Sub OnWriteHeaderContents(writer As XmlDictionaryWriter, messageVersion As MessageVersion)
WriteHeader(writer)
End Sub
Private Overloads Sub WriteHeader(writer As XmlDictionaryWriter)
Dim random = New Random()
Dim nounce(15) As Byte
random.NextBytes(nounce)
' RijndaelManaged
Dim rijn As SymmetricAlgorithm = SymmetricAlgorithm.Create()
rijn.Key = nounce
rijn.IV = nounce
rijn.Mode = CipherMode.ECB
Dim encryptor = rijn.CreateEncryptor(rijn.Key, rijn.IV)
Dim encryptedPassword = EncryptString(Password, encryptor)
' date in ISO 8601 compatible format
Dim createdDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
Dim encryptedCreatedDate = EncryptString(createdDate, encryptor)
Dim rsa As New RSACryptoServiceProvider()
Dim AtPublicKey As String = Certificate.PublicKey.Key.ToXmlString(False)
rsa.FromXmlString(AtPublicKey)
Dim encryptedNounce As String = Convert.ToBase64String(rsa.Encrypt(nounce, False))
writer.WriteRaw(String.Format("<UsernameToken>" &
"<Username>{0}</Username>" &
"<Nonce>{1}</Nonce>" &
"<Password>{2}</Password>" &
"<Created>{3}</Created>" &
"</UsernameToken>",
UserName,
encryptedNounce,
encryptedPassword,
encryptedCreatedDate))
End Sub
Private Function EncryptString(text As String, encryptor As ICryptoTransform) As String
Using textStream As New MemoryStream()
Using cryptoStream As New CryptoStream(textStream, encryptor, CryptoStreamMode.Write)
Using textWriter As New StreamWriter(cryptoStream)
textWriter.Write(text)
End Using
Return Convert.ToBase64String(textStream.ToArray())
End Using
End Using
End Function
End Class
Imports System.ServiceModel.Description
Imports System.ServiceModel.Channels
Public Class ATSecurityInspectorBehavior
Implements IEndpointBehavior
Public Property ClientInspector As AddHeadersMessageInspector
Public Sub New(clientInspector As AddHeadersMessageInspector)
Me.ClientInspector = clientInspector
End Sub
Public Sub Validate(endpoint As ServiceEndpoint) Implements System.ServiceModel.Description.IEndpointBehavior.Validate
End Sub
Public Sub AddBindingParameters(endpoint As ServiceEndpoint, bindingParameters As BindingParameterCollection) Implements System.ServiceModel.Description.IEndpointBehavior.AddBindingParameters
End Sub
Public Sub ApplyDispatchBehavior(endpoint As ServiceEndpoint, endpointDispatcher As ServiceModel.Dispatcher.EndpointDispatcher) Implements System.ServiceModel.Description.IEndpointBehavior.ApplyDispatchBehavior
End Sub
Public Sub ApplyClientBehavior(endpoint As ServiceEndpoint, clientRuntime As ServiceModel.Dispatcher.ClientRuntime) Implements System.ServiceModel.Description.IEndpointBehavior.ApplyClientBehavior
If (Me.ClientInspector Is Nothing) Then
Throw New InvalidOperationException("Caller must supply ClientInspector.")
End If
clientRuntime.MessageInspectors.Add(ClientInspector)
End Sub
End Class
Public Class AutoridadeTributariaManager
Public Function SendTransportDocument(userName As String, password As String, request As ATTransportServiceReference.StockMovement) As ATTransportServiceReference.StockMovementResponse
dim atPublicKey = New X509Certificate2(System.Configuration.ConfigurationManager.AppSettings("ATPublicKeyPath"))
Using client As New ATTransportServiceReference.documentosTransporteClient()
client.Endpoint.Behaviors.Add(New ATSecurityInspectorBehavior(New AddHeadersMessageInspector(New ATSecurityHeader(userName, password, atPublicKey))))
Dim response = client.envioDocumentoTransporte(request)
Return response
End Using
End Function
End Class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment