我正在努力为我的 WCF 数据服务/ODATA 服务器添加 WIF 支持,我想做的第一件事是创建一个 nUnit 测试,它将某种身份传递给所述服务器。我相信这属于活跃客户的范畴:没有用户界面;我想调用 app.config 已建立的提供商(Google、Yahoo、Windows Live 或其他提供商)来获取我的身份令牌。坦率地说,这并不重要,只是它或多或少总是可以访问的,并且没有管理来运行测试。(如果有一些主机应用程序可以包含在我的解决方案中以充当 IP,我会非常满意。)
我所有现有的测试都直接使用 HttpRequest ——我没有使用生成的客户端。在创建 HttpRequest 对象时,我会检查是否已经有一个身份验证令牌可以放入我的标头中。如果没有,我正在尝试这样的事情:
using (WSTrustChannelFactory factory = new WSTrustChannelFactory(
new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
new EndpointAddress(new Uri("https://dev.login.live.com/wstlogin.srf"))))
{
factory.Credentials.UserName.UserName = "MYUSERNAME";
factory.Credentials.UserName.Password = "MYPASSWORD";
factory.TrustVersion = TrustVersion.WSTrust13;
WSTrustChannel channel = null;
try
{
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress("http://localhost:60711/Service"),
KeyType = WSTrust13Constants.KeyTypes.Bearer,
};
channel = (WSTrustChannel)factory.CreateChannel();
return channel.Issue(rst);
}
finally
{
if (null != channel)
{
channel.Abort();
}
factory.Abort();
}
}
所以开始...我什至不知道我是否针对 IP 的正确 URI,但是当我更改它时,我得到了 404,所以我想我可能在正确的轨道上。目前,channel.Issue 方法返回一个带有 FaultException 类型内部异常的 MessageSecurityException,并注明“无效请求”。FaultException 有一个 Name=Sender 和 Namespace=http://www.w3.org/2003/05/soap-envelope 的 Code,然后它有一个 Name=InvalidRequest 和 Namespace=http://schemas.xmlsoap 的 SubCode。 org/ws/2005/02/信任。我不知道如何处理这些信息。:)
如果我问一个非常基本的问题,我很抱歉。我只关注了几天的身份验证,还不知道我的方法。谢谢你的帮助!
编辑——解决方案
Eugenio 是对的——我正在做一些重量级的事情,它更多的是集成测试的东西。我放弃了 Google/Yahoo/Live 的东西,并找到了SelfSTS的修改版本,我将它拼凑到我的项目中。我还不完全明白发生了什么,但我取回了一个 SAML 令牌。这是最终代码:
var binding = new WS2007HttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = true;
using (var trustChannelFactory = new WSTrustChannelFactory(binding, new EndpointAddress(new Uri("http://localhost:8099/STS/Username"), new DnsEndpointIdentity("adventureWorks"), new AddressHeaderCollection())))
{
trustChannelFactory.Credentials.UserName.UserName = MYUSERNAME;
trustChannelFactory.Credentials.UserName.Password = MYPASSWORD;
trustChannelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
WSTrustChannel channel = null;
try
{
var rst = new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue)
{
AppliesTo = new EndpointAddress("http://localhost:60711/Service"),
KeyType = WSTrust13Constants.KeyTypes.Bearer
};
channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
GenericXmlSecurityToken token = channel.Issue(rst) as GenericXmlSecurityToken;
((IChannel)channel).Close();
channel = null;
trustChannelFactory.Close();
string tokenString = token.TokenXml.OuterXml;
return tokenString;
}
finally
{
if (null != channel)
{
((IChannel)channel).Abort();
}
trustChannelFactory.Abort();
}
}
(这段代码也是从我得到修改后的 SelfSTS 的同一个地方提取的——谢谢,Wade Wegner!)
我不确定“adventureWorks”的使用。我使用的 SelfSTS 版本作为配置中的 issuername,但我没有检查是否有任何相关性。
所以......现在破解我的实际服务器,以便它可以弄清楚如何处理 SAML!