1

WCF 新手,但非常熟悉过去的 WSE* 范例。我发现 WCF 的可配置性(阅读:复杂性)是一个相当大的挑战。

我正在尝试使用 .NET 4.0 WCF 客户端来使用我们政府提供的在 WebSphere Application Server/6.1 上运行的 Web 服务。

他们的方案使用 UsernameToken 通过 HTTPS 传输加密进行身份验证和交换 SAML 断言。此 SAML 断言用于其服务的其余操作。

当尝试“登录”(即获取 SAML 断言)时,当 WCF 尝试处理返回的 SOAP 时,我收到以下异常:

“找不到 'System.IdentityModel.Tokens.SamlSecurityToken' 令牌类型的令牌身份验证器。根据当前的安全设置,无法接受该类型的令牌。”

这是我的设置文件:

<system.serviceModel>
<client>
  <endpoint binding="basicHttpBinding"
            bindingConfiguration="Default"
            contract="ServiceProxy.Login"
            name="Login" />
</client>
<bindings>
  <basicHttpBinding>
    <binding name="Default">
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="None"/>
        <message clientCredentialType="UserName" />
      </security>
    </binding>

  </basicHttpBinding>
</bindings>
</system.serviceModel>

这是 SOAP 请求:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <!-- Removed -->
    <ActivityId CorrelationId="c9363270-1b33-4ffe-90b0-427feebcebf6" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">cadd6a3c-7b36-46eb-9130-390227effc08</ActivityId>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <u:Timestamp u:Id="_0">
        <u:Created>2012-12-13T22:50:22.308Z</u:Created>
        <u:Expires>2012-12-13T22:55:22.308Z</u:Expires>
      </u:Timestamp>
      <o:UsernameToken u:Id="uuid-91607d82-da2c-4004-93b6-baf5973ba057-1">
        <o:Username>
          <!-- Removed-->
        </o:Username>
        <o:Password>
          <!-- Removed-->
        </o:Password>
      </o:UsernameToken>
    </o:Security>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <LoginRequest xmlns="http://snipped.url/Services.xsd"></LoginRequest>
  </s:Body>
</s:Envelope>

这是使 WCF 窒息的响应:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
      <!-- Removed -->
      <o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:mustUnderstand="1">
        <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="id-94ef81a2eba3b246e284f72c3313e32ababe9482" IssueInstant="2012-12-13T22:50:23.930Z" Issuer="http://www.forumsys.com/sentry" MajorVersion="1" MinorVersion="1">
          <saml:Conditions NotBefore="2012-12-13T22:50:23.930Z" NotOnOrAfter="2012-12-14T08:50:23.930Z"></saml:Conditions>
          <saml:AuthenticationStatement AuthenticationInstant="2012-12-13T22:50:23.930Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password">
            <saml:Subject>
              <saml:NameIdentifier>
                <!-- Removed-->
              </saml:NameIdentifier>
              <saml:SubjectConfirmation>
                <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod>
              </saml:SubjectConfirmation>
            </saml:Subject>
            <saml:SubjectLocality>
              <!-- Removed-->
            </saml:SubjectLocality>
          </saml:AuthenticationStatement>
          <saml:AttributeStatement>
            <saml:Subject>
              <saml:NameIdentifier>
                <!-- Removed-->
              </saml:NameIdentifier>
              <saml:SubjectConfirmation>
                <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod>
              </saml:SubjectConfirmation>
            </saml:Subject>
            <saml:Attribute AttributeName="SMSESSION" AttributeNamespace="http://www.forumsys.com/sentry">
              <saml:AttributeValue>
                <!-- Removed-->
              </saml:AttributeValue>
            </saml:Attribute>
          </saml:AttributeStatement>
          </saml:Assertion>
        <u:Timestamp xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" u:Id="_0">
          <u:Created>2012-12-13T22:50:22.308Z</u:Created>
          <u:Expires>2012-12-13T22:55:22.308Z</u:Expires>
        </u:Timestamp>
        <o:UsernameToken xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" u:Id="uuid-91607d82-da2c-4004-93b6-baf5973ba057-1">
          <o:Username>
            <!-- Removed-->
          </o:Username>
          <o:Password>
            <!-- Removed-->
          </o:Password>
        </o:UsernameToken>
      </o:Security>
    </soapenv:Header>
    <soapenv:Body>
      <wn1:LoginResponse xmlns:wn1="http://snipped.url/Services.xsd">
        <wn1:Status>session counter updated</wn1:Status>
      </wn1:LoginResponse>
    </soapenv:Body>
</soapenv:Envelope>

上述响应是一个成功的响应,并且与在 WSE2/3 上运行的先前版本相匹配(由于其他原因,我无法继续使用)。

如何让 WCF 确认上述响应有效?或者也许只是为了让它忽略它无法解析它的事实,我也许可以手动解析它。

我难住了!

更新#1:

我开始走自定义客户端凭据路线。这看起来很有希望,虽然有点复杂。

如果你想走这条路...

1) 在此处查看 MS 文章系列:http: //msdn.microsoft.com/en-us/library/ms730868 (v=vs.100).aspx

2) 另请参阅 WCF 示例 WCF\Extensibility\Security\SamlTokenProvider。

3)使用此方法的博客文章:http: //bronumski.blogspot.com/2011/11/this-has-been-hanging-around-in-my.html

这应该允许您在没有 WIF 的情况下使用 SAML 断言。

更新#2:

请参阅下面的答案和最终解决方案。

4

2 回答 2

1

我建议为了获得 saml,不要使用 wcf 安全性。只需通过自定义标头(可能使用消息检查器)将用户名添加到请求中,并使用相同的方法从响应中提取 SAML。然后以同样的方式将 saml 推到每个进一步的信封中。

于 2012-12-15T22:57:47.280 回答
0

最终接受了 Yaron 的建议,并编写了几个自定义检查器和行为。

使用 proxy.ClientCredentials.UserName.UserName/Password 是上面报告的原始异常的原因。它会在处理后续添加的行为之前尝试并验证返回的 SOAP,从而导致每次 SAML 断言上的响应验证错误。

第一个行为/检查员有两个工作:

1)在请求端,手动添加UsernameToken节点;

2)在响应端,提取saml token;确保从 SOAP 中删除任何有问题的“安全”XML 节点并重新处理回复(防止出现类似原始帖子的另一个错误);保存 SAML 响应以备后用。

第二个行为/检查器将共享 SAML 断言注入到请求的其余部分中。

这是所需的配置:

  <basicHttpBinding>
    <binding name="Default">
      <security mode="Transport">
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </basicHttpBinding>

这是一些代码(注意删除了 ClientCredentials 行为):

var proxy = new LoginClient();
proxy.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
var initLogin = new InitialLoginMessageBehavior("username", "password");
proxy.Endpoint.Behaviors.Add(initLogin);
var response = proxy.Login();

//use the SAML response
var proxy2 = new OtherClient();
proxy2.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
proxy2.Endpoint.Behaviors.Add(new SamlAuthenticationMessageBehavior(initLogin.Saml));

var response2 = proxy2.DoSomethingElse();

创建行为和检查器所需的一切:

http://msdn.microsoft.com/en-us/library/aa717047(v=vs.100).aspx

http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/19/wcf-extensibility-message-inspectors.aspx

于 2012-12-20T23:34:08.590 回答