问题描述
我正在尝试从WIF 3.5转移到WIF 4.5。但是,事实证明转换比我预期的要困难。这些问题将与代码中的注释相对应。
完整错误消息:
System.Web.Services.Protocols.soapException:'System.Web.Services.Protocols.soapException:身份验证失败--->
System.ServiceModel.Security.SecurityNegotiationException:安全 无法打开频道,因为与远程服务器进行安全协商 端点失败。这可能是由于缺席或不正确 在EndpointAddress中指定的EndpointIdentity用于创建 渠道。请验证指定或暗示的EndpointIdentity EndpointAddress可以正确识别远程端点。
无法打开安全通道,因为与 远程端点已失败。这可能是由于缺席或不正确 在EndpointAddress中指定的EndpointIdentity用于创建 渠道。请验证指定或暗示的EndpointIdentity EndpointAddress可以正确识别远程端点。
#1。
需要哪种用户名/密码组合?#2。这是抛出SecurityNegotiationException的地方。我到底想念什么?
那么,我要离开吗,还是我想念的简单东西?我是否需要完全重写WSTrustChannelFactory
的创建方式?
代码:
public string GetToken(string url,string domain,string realm,string username,string password)
{
string rp = realm;
string token = "";
WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory
(
new WSHttpBinding(SecurityMode.TransportWithMessageCredential),new EndpointAddress(new Uri(url))
);
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.Credentials.Windows.ClientCredential.Domain = domain;
trustChannelFactory.Credentials.Windows.ClientCredential.UserName = username; // #1; not sure which pair is needed?
trustChannelFactory.Credentials.Windows.ClientCredential.Password = password;
trustChannelFactory.Credentials.UserName.Password = password;
trustChannelFactory.Credentials.UserName.UserName = username;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
try
{
RequestSecurityToken rst = new RequestSecurityToken(RequestTypes.Issue,KeyTypes.Bearer);
rst.AppliesTo = new EndpointReference(rp);
rst.TokenType = SecurityTokenTypes.Saml;
WSTrustChannel channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
GenericXmlSecurityToken token = channel.Issue(rst) as GenericXmlSecurityToken; // #2; Exception thrown here
token = token.TokenXml.OuterXml;
}
catch (SecurityNegotiationException e)
{
LogError("Authentication Failed",e);
}
catch (TimeoutException e)
{
LogError("Unable to authenticate",e);
}
catch (CommunicationException e)
{
LogError("Communication exception",e);
}
catch (Exception e)
{
LogError("UnkNown exception",e);
}
return token;
}
解决方法
您需要使用 SecurityTokenHandlerCollection
public SecurityToken GetToken(string url,string realm,string username,string password)
{
string rp = realm;
WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential,false);
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.EstablishSecurityContext = false;
EndpointAddress endpoint = new EndpointAddress(url);
WSTrustChannelFactory factory = new WSTrustChannelFactory(binding,endpoint);
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.UserName.UserName = username;
factory.Credentials.UserName.Password = password;
WSTrustChannel channel = (WSTrustChannel) factory.CreateChannel();
RequestSecurityToken rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,KeyType = KeyTypes.Bearer,AppliesTo = new EndpointReference(rp),TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"
};
GenericXmlSecurityToken genericXmlSecurityToken = (GenericXmlSecurityToken) channel.Issue(rst,out RequestSecurityTokenResponse rstr);
SecurityTokenHandlerCollection tokenHandlers = new SecurityTokenHandlerCollection(
new SecurityTokenHandler[]
{
new SamlSecurityTokenHandler(),new Saml2SecurityTokenHandler()
}
);
tokenHandlers.Configuration.AudienceRestriction = new AudienceRestriction();
tokenHandlers.Configuration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(rp));
TrustedIssuerNameRegistry trustedIssuerNameRegistry = new TrustedIssuerNameRegistry();
tokenHandlers.Configuration.IssuerNameRegistry = trustedIssuerNameRegistry;
SecurityToken token =
tokenHandlers.ReadToken(
new XmlTextReader(new StringReader(genericXmlSecurityToken.TokenXml.OuterXml)));
return token;
}
public class TrustedIssuerNameRegistry : IssuerNameRegistry
{
public override string GetIssuerName(SecurityToken securityToken)
{
return "Trusted Issuer";
}
}
,
我们决定暂时继续使用WIF 3.5,并且将完全重写WIF 4.5,而不是尝试做一些不可能的事情。
发生了太多变化,文档不足,无法将现有代码从WIF 3.4提升到WIF 4.5