我正在尝试使用WSE 3.0自定义策略创建.NET客户端。我有本地wsdl,因为服务使用https和证书保护。请求SOAP消息需要使用来自客户端的证书进行签名和加密以进行签名,并使用服务提供者进行加密。我使用了在MSDN上找到的自定义安全断言,这是我的课程的样子:
namespace RegistryProxy
{
class CustomSecurityAssertion : SecurityPolicyAssertion
{
TokenProvider<X509SecurityToken> serviceX509TokenProviderValue;
TokenProvider<X509SecurityToken> clientX509TokenProviderValue;
public TokenProvider<X509SecurityToken> ClientX509TokenProvider
{
get
{
return clientX509TokenProviderValue;
}
set
{
clientX509TokenProviderValue = value;
}
}
public TokenProvider<X509SecurityToken> ServiceX509TokenProvider
{
get
{
return serviceX509TokenProviderValue;
}
set
{
serviceX509TokenProviderValue = value;
}
}
public CustomSecurityAssertion()
: base()
{
}
public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
{
return new CustomSecurityClientOutputFilter(this);
}
public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
{
return new CustomSecurityClientInputFilter(this);
}
public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
{
return new CustomSecurityServerInputFilter(this);
}
public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
{
return new CustomSecurityServerOutputFilter(this);
}
public override void ReadXml(System.Xml.XmlReader reader, IDictionary<string, Type> extensions)
{
if (reader == null)
throw new ArgumentNullException("reader");
if (extensions == null)
throw new ArgumentNullException("extensions");
bool isEmpty = reader.IsEmptyElement;
base.ReadAttributes(reader);
reader.ReadStartElement("CustomSecurityAssertion");
if (!isEmpty)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "clientToken")
{
reader.ReadStartElement();
reader.MoveToContent();
// Get the registed security token provider for X.509 certificate security credentials.
Type type = extensions[reader.Name];
object instance = Activator.CreateInstance(type);
if (instance == null)
throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));
TokenProvider<X509SecurityToken> clientProvider = instance as TokenProvider<X509SecurityToken>;
// Read the child elements that provide the details about the client's X.509 certificate.
clientProvider.ReadXml(reader, extensions);
this.ClientX509TokenProvider = clientProvider;
reader.ReadEndElement();
}
if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "serviceToken")
{
reader.ReadStartElement();
reader.MoveToContent();
// Get the registed security token provider for X.509 certificate security credentials.
Type type = extensions[reader.Name];
object instance = Activator.CreateInstance(type);
if (instance == null)
throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));
TokenProvider<X509SecurityToken> serviceProvider = instance as TokenProvider<X509SecurityToken>;
// Read the child elements that provide the details about the Web service's X.509 certificate.
serviceProvider.ReadXml(reader, extensions);
this.ServiceX509TokenProvider = serviceProvider;
reader.ReadEndElement();
}
base.ReadElements(reader, extensions);
reader.ReadEndElement();
}
}
public override IEnumerable<KeyValuePair<string, Type>> GetExtensions()
{
// Add the CustomSecurityAssertion custom policy assertion to the list of registered
// policy extensions.
List<KeyValuePair<string, Type>> extensions = new List<KeyValuePair<string, Type>>();
extensions.Add(new KeyValuePair<string, Type>("CustomSecurityAssertion", this.GetType()));
if (serviceX509TokenProviderValue != null)
{
// Add any policy extensions that read child elements of the <serviceToken> element
// to the list of registered policy extensions.
IEnumerable<KeyValuePair<string, Type>> innerExtensions = serviceX509TokenProviderValue.GetExtensions();
if (innerExtensions != null)
{
foreach (KeyValuePair<string, Type> extension in innerExtensions)
{
extensions.Add(extension);
}
}
}
if (clientX509TokenProviderValue != null)
{
// Add any policy extensions that read child elements of the <clientToken> element
// to the list of registered policy extensions.
IEnumerable<KeyValuePair<string, Type>> innerExtensions = clientX509TokenProviderValue.GetExtensions();
if (innerExtensions != null)
{
foreach (KeyValuePair<string, Type> extension in innerExtensions)
{
extensions.Add(extension);
}
}
}
return extensions;
}
// </snippet16
}
class RequestState
{
SecurityToken clientToken;
SecurityToken serverToken;
public RequestState(SecurityToken cToken, SecurityToken sToken)
{
clientToken = cToken;
serverToken = sToken;
}
public SecurityToken ClientToken
{
get { return clientToken; }
}
public SecurityToken ServerToken
{
get { return serverToken; }
}
}
class CustomSecurityServerInputFilter : ReceiveSecurityFilter
{
public CustomSecurityServerInputFilter(CustomSecurityAssertion parentAssertion)
: base(parentAssertion.ServiceActor, false)
{
}
public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security)
{
SecurityToken clientToken = null;
SecurityToken serverToken = null;
// Ensure incoming SOAP messages are signed and encrypted.
foreach (ISecurityElement elem in security.Elements)
{
if (elem is MessageSignature)
{
MessageSignature sig = (MessageSignature)elem;
clientToken = sig.SigningToken;
}
if (elem is EncryptedData)
{
EncryptedData enc = (EncryptedData)elem;
serverToken = enc.SecurityToken;
}
}
if (clientToken == null || serverToken == null)
throw new Exception("Incoming message did not meet security requirements");
RequestState state = new RequestState(clientToken, serverToken);
envelope.Context.OperationState.Set(state);
}
}
class CustomSecurityServerOutputFilter : SendSecurityFilter
{
public CustomSecurityServerOutputFilter(CustomSecurityAssertion parentAssertion)
: base(parentAssertion.ServiceActor, false)
{
}
public override void SecureMessage(SoapEnvelope envelope, Security security)
{
RequestState state = envelope.Context.OperationState.Get<RequestState>();
// Sign the message with the Web service's security token.
security.Tokens.Add(state.ServerToken);
security.Elements.Add(new MessageSignature(state.ServerToken));
// Encrypt the message with the client's security token.
security.Elements.Add(new EncryptedData(state.ClientToken));
}
}
class CustomSecurityClientInputFilter : ReceiveSecurityFilter
{
public CustomSecurityClientInputFilter(CustomSecurityAssertion parentAssertion)
: base(parentAssertion.ServiceActor, true)
{
}
public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security)
{
RequestState state;
bool signed = false;
bool encrypted = false;
// Get the request state out of the operation state.
state = envelope.Context.OperationState.Get<RequestState>();
// Make sure the message was signed with the server's security token.
foreach (ISecurityElement elem in security.Elements)
{
if (elem is MessageSignature)
{
MessageSignature sig = (MessageSignature)elem;
if (sig.SigningToken.Equals(state.ServerToken))
signed = true;
}
if (elem is EncryptedData)
{
EncryptedData enc = (EncryptedData)elem;
if (enc.SecurityToken.Equals(state.ClientToken))
encrypted = true;
}
}
if (!signed || !encrypted)
throw new Exception("Response message does not meet security requirements");
}
}
class CustomSecurityClientOutputFilter : SendSecurityFilter
{
SecurityToken clientToken;
SecurityToken serverToken;
public CustomSecurityClientOutputFilter(CustomSecurityAssertion parentAssertion)
: base(parentAssertion.ServiceActor, true)
{
ISecurityTokenManager stm = SecurityTokenManager.GetSecurityTokenManagerByTokenType(WSTrust.TokenTypes.X509v3);
X509SecurityTokenManager x509tm = stm as X509SecurityTokenManager;
x509tm.DefaultSessionKeyAlgorithm = "AES128";
x509tm.DefaultKeyAlgorithm = "RSA15";
// Get the client security token.
clientToken = X509TokenProvider.CreateToken(StoreLocation.LocalMachine, StoreName.My, "serial removed", X509FindType.FindBySerialNumber);
// Get the server security token.
serverToken = X509TokenProvider.CreateToken(StoreLocation.LocalMachine, StoreName.My, "serial removed",X509FindType.FindBySerialNumber);
}
public override void SecureMessage(SoapEnvelope envelope, Security security)
{
ISecurityTokenManager stm = X509SecurityTokenManager.GetSecurityTokenManagerByTokenType(WSTrust.TokenTypes.X509v3);
X509SecurityTokenManager x509tm = stm as X509SecurityTokenManager;
x509tm.DefaultSessionKeyAlgorithm = "AES128";
x509tm.DefaultKeyAlgorithm = "RSA15";
// Sign the SOAP message with the client's security token.
security.Tokens.Add(clientToken);
security.Elements.Add(new MessageSignature(clientToken));
// Encrypt the SOAP message with the client's security token.
security.Elements.Add(new EncryptedData(serverToken));
// Encrypt the client's security token with the server's security token.
security.Elements.Add(new EncryptedData(serverToken, "#" + clientToken.Id));
// Store the client and server security tokens in the request state.
RequestState state = new RequestState(clientToken, serverToken);
// Store the request state in the proxy's operation state.
// This makes these tokens accessible when SOAP responses are
// verified to have sufficient security requirements.
envelope.Context.OperationState.Set(state);
}
}
}
在set into project in class之后,我创建了一个wse3policyCache.config来使用证书:
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="CustomSecurityAssertion" type="GiftRegistryProxy.CustomSecurityAssertion,GiftRegistryProxy" />
</extensions>
<policy name="ClientPolicy">
<CustomSecurityAssertion>
<clientToken>
<x509
storeLocation="LocalMachine"
storeName="My"
findValue="serial number"
findType="FindBySerialNumber" />
</clientToken>
<serviceToken>
<x509
storeLocation="LocalMachine"
storeName="My"
findValue="serial number"
findType="FindBySerialNumber" />
</serviceToken>
</CustomSecurityAssertion>
</policy>
</policies>
当一切都设置好后,我运行我的客户端,我的客户端返回消息:
请求已中止:无法创建SSL / TLS安全通道。
当我看网络监视器时,它说
TLS:TLS Rec Layer-1 HandShake: Client Hello.
TLS:TLS Rec Layer-1 HandShake: Server Hello. Certificate. Certificate.
TLS:TLS Rec Layer-1 HandShake: Certificate. Client Key Exchange.; TLS Rec Layer-2 Cipher Change Spec; TLS Rec Layer-3 HandShake: Encrypted Handshake Message.
TLS:TLS Rec Layer-1 Encrypted Alert --Problem
任何人都可以解释为什么会发生这种情况并在可能的情况下在此输入吗?