C# 未指定用于在url处与联合身份验证服务通信的绑定

C# 未指定用于在url处与联合身份验证服务通信的绑定,c#,wpf,wcf,adfs,C#,Wpf,Wcf,Adfs,我目前正在使用ADFS作为安全令牌服务。我想将WCF服务与ADF联合。我创建了WCF服务,并使用Federation实用程序添加了ADF的STS引用 为了使用联邦wcf服务,我创建了WPF应用程序并添加了服务引用。我使用以下代码调用了服务api var client=new SecureWpfApplication.ServiceReference1.Service1Client(); Uri=新的Uri(“http://tempuri.org/"); ICredentials credenti

我目前正在使用ADFS作为安全令牌服务。我想将WCF服务与ADF联合。我创建了WCF服务,并使用Federation实用程序添加了ADF的STS引用

为了使用联邦wcf服务,我创建了WPF应用程序并添加了服务引用。我使用以下代码调用了服务api

var client=new SecureWpfApplication.ServiceReference1.Service1Client();
Uri=新的Uri(“http://tempuri.org/");
ICredentials credentials=CredentialCache.DefaultCredentials;
NetworkCredential=credentials.GetCredential(uri,“基本”);
client.ClientCredentials.Windows.ClientCredential=凭证;
client.ClientCredentials.SupportInteractive=false;
客户端.GetData(323);
我收到错误“未指定用于在https://{ADFS server}/ADFS/services/trust/13/usernamemix处与联合身份验证服务通信的绑定”

如何解决这个问题

我创建了wcf服务配置,如下所示

<services>
  <service name="SecureWcfService.Service1" behaviorConfiguration="SecureWcfService.ServiceBehaviour">
    <endpoint address="https://wcfserver/SampleWcfService/Service1.svc" binding="ws2007FederationHttpBinding" contract="SecureWcfService.IService1" bindingConfiguration="SecureWcfService.IService1_ws2007FederationHttpBinding" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>
<behaviors>
<serviceBehaviors>
    <behavior name="SecureWcfService.ServiceBehaviour">
      <federatedServiceHostConfiguration name="SecureWcfService.Service" />
      <serviceMetadata httpGetEnabled="true" />
      <serviceCredentials>
        <serviceCertificate findValue="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
      </serviceCredentials>
    </behavior>
</serviceBehaviors>
</behaviors>
<extensions>
    <behaviorExtensions>
        <add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </behaviorExtensions>
</extensions>
<bindings>
<ws2007FederationHttpBinding>
    <binding name="SecureWcfService.IService1_ws2007FederationHttpBinding">
        <security mode="Message">
            <message>
                <issuerMetadata address="https://adfsserver/adfs/services/trust/mex" />
                <claimTypeRequirements>
                    <add claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" />
                    <add claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" isOptional="true" />
                </claimTypeRequirements>
            </message>
        </security>
    </binding>
</ws2007FederationHttpBinding>
</bindings>
<microsoft.identityModel>
    <service>
        <audienceUris>
            <add value="https://wcfserver/SecureWcfService/Service1.svc" />
        </audienceUris>
        <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <trustedIssuers>
                <add thumbprint="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="http://asfsserver/adfs/services/trust" />
                <add thumbprint="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="http://adfsserver/adfs/services/trust" />
            </trustedIssuers>
        </issuerNameRegistry>
        <certificateValidation certificateValidationMode="None" />
    </service>
</microsoft.identityModel>   


'未指定。

在我看来,在继续使用WCF服务之前,您似乎需要遵循更多教程和/或阅读更多网页。如何使用WCF对于此网站来说是一个太宽泛的主题,但基本上,您需要在配置文件中定义一个绑定元素,以指定要使用联合服务在您的WCF服务中

仔细阅读MSDN上的页面。从链接页面:

在bindings部分中创建可用于与安全令牌服务通信的元素。有关创建绑定的详细信息,请参阅如何:在配置中指定服务绑定


您也可以阅读MSDN上的页面以获得进一步的背景阅读。

我实现这一点的方法是根本不使用通过添加服务引用生成的配置,而是通过编程来完成。这就是我的工作:

//Helper to get SAML token from STS
public static SecurityToken GetSamlToken(string realm, string trustUrl, string userName, string password, string keyType, SecurityToken actAsToken = null)
{
    var factory = new WSTrustChannelFactory(
        //You will need to use WindowsWSTrustBinding here I think
        new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
        trustUrl
    );

    factory.TrustVersion = TrustVersion.WSTrust13;

    //Here you would use Windows credentials instead of username/password
    factory.Credentials.UserName.UserName = userName;
    factory.Credentials.UserName.Password = password;

    var rst = new RequestSecurityToken
    {
        RequestType = RequestTypes.Issue,
        TokenType = TokenTypes.Saml2TokenProfile11,
        KeyType = keyType, //I used KeyTypes.Bearer here
        AppliesTo = new EndpointReference(realm)
    };

    if (actAsToken != null)
    {
        rst.ActAs = new SecurityTokenElement(actAsToken);
    }

    var token = factory.CreateChannel().Issue(rst);

    return token;
}

var token = GetSamlToken(...);

var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message); 
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;

var factory = new ChannelFactory<IService1>(binding, new EndpointAddress(serviceEndpoint));

ChannelFactoryOperations.ConfigureChannelFactory<IService1>(factory);

factory.Credentials.SupportInteractive = false;
factory.Credentials.UseIdentityConfiguration = true;

var channel = factory.CreateChannelWithIssuedToken<IService1>(token);

channel.CallSomeServiceMethod();
//帮助程序从STS获取SAML令牌
公共静态SecurityToken GetSamlToken(字符串域、字符串信任URL、字符串用户名、字符串密码、字符串密钥类型、SecurityToken actAsToken=null)
{
var工厂=新工厂(
//我想您需要在这里使用WindowsWSTrustBinding
新用户名WSTrustBinding(SecurityMode.TransportWithMessageCredential),
信任URL
);
factory.TrustVersion=TrustVersion.WSTrust13;
//在这里,您将使用Windows凭据而不是用户名/密码
factory.Credentials.UserName.UserName=用户名;
factory.Credentials.UserName.Password=密码;
var rst=新的RequestSecurityToken
{
RequestType=RequestTypes.Issue,
TokenType=TokenTypes.Saml2TokenProfile11,
KeyType=KeyType,//我在这里使用了KeyTypes.Bearer
AppliesTo=新端点引用(领域)
};
if(actAsToken!=null)
{
rst.ActAs=新的SecurityTokenElement(actAsToken);
}
var token=factory.CreateChannel().Issue(rst);
返回令牌;
}
var-token=GetSamlToken(…);
var binding=newWS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message);
binding.Security.Message.EstablishSecurityContext=false;
binding.Security.Message.IssuedKeyType=SecurityKeyType.BearerKey;
var factory=newchannelfactory(绑定,新端点地址(serviceEndpoint));
ChannelFactoryOperations.ConfigureChannelFactory(工厂);
factory.Credentials.SupportInteractive=false;
factory.Credentials.UseIdentityConfiguration=true;
var通道=factory.CreateChannelWithIssuedToken(令牌);
channel.CallSomeServiceMethod();

谢谢@mclaaseen。我也通过代码获取令牌。上面提到的答案也有效。但我想通过使用配置隐式获取令牌