.net - clientcredentialtype - wcf https
WCF WS2007FederationHttpBinding con HTTPS (1)
Como comenté la pregunta: después de mucho tiempo dedicado a buscar una solución, parece que WS2007FederationHttpBinding con el Modo de seguridad ''Mensaje'' no debe utilizarse en este contexto debido a la comprobación de identidad del servidor. Todavía es posible usar el mismo certificado en el cargador de SSL y para la identidad del servicio.
Esta es la solución que elegí para mantener el modelo de seguridad y resolver mi problema
Me aparece el siguiente error al intentar conectarme a WCF API que está detrás de un proxy HTTPS:
El certificado del servidor con el nombre ''CN = nombre de host'' falló la verificación de identidad porque su huella digital (''X'') no coincide con la especificada en la identidad del punto final (''Y''). Como resultado, la solicitud HTTPS actual ha fallado. Actualice la identidad del punto final utilizada en el cliente o el certificado utilizado por el servidor.
Donde X es la huella digital del certificado utilizado por el proxy e Y la huella digital del certificado utilizado por el servicio
El problema es que logré obtener un token del STS pero no puedo realizar ninguna llamada de servicio web después de eso.
Reproduje el problema en mi PC utilizando un proxy SSL local, el certificado utilizado en el proxy es de confianza en mi PC. Todo está bien cuando se usa HTTP.
Busqué una solución por varios días y noté este artículo de KB que está cerca de mi problema pero que ya no se aplica (estoy ejecutando el ejemplo y el servidor en .Net 4.5): https://support.microsoft.com/ es-us / kb / 2564823
Qué me estoy perdiendo ?
Aquí está el código:
class Program
{
static void Main(string[] args)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
string serverUrl = ConfigurationManager.AppSettings["ServerURL"];
GenericXmlSecurityToken token = GetToken(serverUrl);
Console.WriteLine("Token Received");
Console.WriteLine(token);
TestServiceClient client = CreateClient(serverUrl, token);
try
{
client.SearchSomething();
Console.WriteLine("SearchSomething succeeded");
}
catch (Exception e)
{
Console.WriteLine("SearchSomething failed :" + e);
}
Console.ReadLine();
}
private static TestServiceClient CreateClient(string serverUrl, GenericXmlSecurityToken token)
{
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message)
{
MaxReceivedMessageSize = int.MaxValue,
MaxBufferPoolSize = int.MaxValue
};
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedTokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1";
binding.Security.Message.NegotiateServiceCredential = false;
binding.ReaderQuotas.MaxDepth = int.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
var uri = new Uri(serverUrl + "Test.Service/Test.Service.svc");
var identity = new X509CertificateEndpointIdentity(new X509Certificate2(ConfigurationManager.AppSettings["ServiceCertificate"], ConfigurationManager.AppSettings["ServiceCertificatePassword"]));
var client = new TestServiceClient(binding, new EndpointAddress(uri, identity));
client.ClientCredentials.SupportInteractive = false;
var customBinding = new CustomBinding();
var bindingElements = binding.CreateBindingElements();
if (serverUrl.Contains("https"))
{
bindingElements.Remove<HttpTransportBindingElement>();
bindingElements.Add(new HttpsTransportBindingElement() { MaxReceivedMessageSize = int.MaxValue });
}
customBinding.Elements.AddRange(bindingElements.ToArray());
client.Endpoint.Binding = customBinding;
var clientCredentials = new SamlClientCredentials(token, client.ClientCredentials);
client.Endpoint.Behaviors.Remove<ClientCredentials>();
client.Endpoint.Behaviors.Add(clientCredentials);
return client;
}
private static GenericXmlSecurityToken GetToken(string serverUrl)
{
string username = ConfigurationManager.AppSettings["Username"];
string password = ConfigurationManager.AppSettings["Password"];
string identityDnsName = ConfigurationManager.AppSettings["IdentityDnsName"];
string ClientCertificate = ConfigurationManager.AppSettings["ClientCertificate"];
string ClientCertificatePassword = ConfigurationManager.AppSettings["ClientCertificatePassword"];
string ServiceCertificate = ConfigurationManager.AppSettings["ServiceCertificate"];
string ServiceCertificatePassword = ConfigurationManager.AppSettings["ServiceCertificatePassword"];
var stsUrl = serverUrl + "Security.Sts/Security.Sts.svc";
GenericXmlSecurityToken token = null;
try
{
var customBinding = new CustomBinding();
var securityBindingElement =
(SymmetricSecurityBindingElement) SecurityBindingElement.CreateMutualCertificateBindingElement();
securityBindingElement.SetKeyDerivation(true);
securityBindingElement.MessageSecurityVersion =
MessageSecurityVersion
.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
securityBindingElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
securityBindingElement.RequireSignatureConfirmation = false;
var securityTokenParameters = new UserNameSecurityTokenParameters()
{
InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient,
RequireDerivedKeys = false
};
securityBindingElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(securityTokenParameters);
customBinding.Elements.Add(securityBindingElement);
if (serverUrl.StartsWith("http:"))
customBinding.Elements.Add(new HttpTransportBindingElement()
{
MaxReceivedMessageSize = int.MaxValue,
MaxBufferPoolSize = int.MaxValue,
MaxBufferSize = int.MaxValue
});
else if (serverUrl.StartsWith("https:"))
customBinding.Elements.Add(new HttpsTransportBindingElement()
{
MaxReceivedMessageSize = int.MaxValue,
MaxBufferPoolSize = int.MaxValue,
MaxBufferSize = int.MaxValue
});
var stsChannelFactory = new WSTrustChannelFactory(customBinding,
new EndpointAddress(new Uri(stsUrl), new DnsEndpointIdentity(identityDnsName)));
stsChannelFactory.Credentials.SupportInteractive = false;
stsChannelFactory.Credentials.ClientCertificate.Certificate = new X509Certificate2(ClientCertificate,
ClientCertificatePassword);
stsChannelFactory.Credentials.ServiceCertificate.DefaultCertificate =
new X509Certificate2(ServiceCertificate, ServiceCertificatePassword);
stsChannelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.None;
stsChannelFactory.Credentials.UserName.UserName = username;
stsChannelFactory.Credentials.UserName.Password = password;
foreach (OperationDescription operationDescription in stsChannelFactory.Endpoint.Contract.Operations)
{
var operationBehavior =
operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (operationBehavior != null)
operationBehavior.MaxItemsInObjectGraph = int.MaxValue;
}
var stsChannel = stsChannelFactory.CreateChannel();
RequestSecurityToken request = new RequestSecurityToken();
request.KeyType = "http://schemas.microsoft.com/idfx/keytype/symmetric";
request.RequestType = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue";
request.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1";
token = (GenericXmlSecurityToken) stsChannel.Issue(request);
return token;
}
catch (Exception e)
{
Console.WriteLine("GetToken Exception :" + e);
}
return token;
}
}
internal class SamlClientCredentials : ClientCredentials
{
public GenericXmlSecurityToken Token { get; private set; }
public SamlClientCredentials(GenericXmlSecurityToken token, ClientCredentials clientCredentials)
: base(clientCredentials)
{
Token = token;
}
protected override ClientCredentials CloneCore()
{
return new SamlClientCredentials(Token, this);
}
public override SecurityTokenManager CreateSecurityTokenManager()
{
return new SamlSecurityTokenManager(this);
}
}
internal class SamlSecurityTokenManager : ClientCredentialsSecurityTokenManager
{
private SamlClientCredentials clientCredentials;
public SamlSecurityTokenManager(SamlClientCredentials clientCredentials)
: base(clientCredentials)
{
this.clientCredentials = clientCredentials;
}
public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
{
if (tokenRequirement.TokenType == SecurityTokenTypes.Saml || tokenRequirement.TokenType == "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1")
return new SamlSecurityTokenProvider(this.clientCredentials.Token);
return base.CreateSecurityTokenProvider(tokenRequirement);
}
}
internal class SamlSecurityTokenProvider : SecurityTokenProvider
{
private readonly GenericXmlSecurityToken token;
public SamlSecurityTokenProvider(GenericXmlSecurityToken token)
{
this.token = token;
}
protected override SecurityToken GetTokenCore(TimeSpan timeout)
{
return token;
}
}