带有ACS颁发令牌和WIF的MessageSecurityException

时间:2013-04-26 02:29:21

标签: wcf wif

我将ACS /服务标识用作临时STS,同时我将事情发布到位。不幸的是,虽然我似乎能够从ACS获得SAML 1.1令牌,但是第二次尝试将其传递到我的WCF服务中时,事情就变得疯狂了。据我所知,令牌没有过期(它被及时使用),我不确定它是如何无效的,我没有做任何关于日志的事情已经向我展示了什么可能是错误的任何细节。我很想把责任归咎于绑定,因为我之前从未做过正式的WCF / WIF绑定。任何人都可以看到我使用的客户端/服务器绑定有什么问题(客户端是通过服务引用生成的),还是建议一个替代的调查途径?

BTW,服务器和客户端都在同一台开发机器上运行。

的Web.config:

<configuration>
  <configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  </configSections>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    <add key="ida:FederationMetadataLocation" value="--omitted--" />
    <add key="ida:ProviderSelection" value="productionSTS" />
  </appSettings>
  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <system.web>
    <compilation debug="true" targetFramework="4.5">
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </assemblies>
    </compilation>
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials useIdentityConfiguration="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add scheme="https" binding="ws2007FederationHttpBinding" />
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <bindings>
      <ws2007FederationHttpBinding>
        <binding name="">
          <security mode="TransportWithMessageCredential">
            <message issuedKeyType="BearerKey" issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"/>
          </security>
        </binding>
      </ws2007FederationHttpBinding>
    </bindings>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <!--
      To browse web app root directory during debugging, set the value below to true.
      Set to false before deployment to avoid disclosing web app folder information.
    -->
    <directoryBrowse enabled="true" />
  </system.webServer>
  <system.identityModel>
    <identityConfiguration>
      <audienceUris>
        <add value="https://localhost:44300/Service1.svc" />
      </audienceUris>
      <issuerNameRegistry>
        <trustedIssuers>
          <add name="--omitted--" thumbprint="--omitted--"/>
        </trustedIssuers>
      </issuerNameRegistry>
      <certificateValidation certificateValidationMode="None"/>
    </identityConfiguration>
  </system.identityModel>
</configuration>

App.config中:

  <system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IService1" />
        </basicHttpBinding>
        <ws2007FederationHttpBinding>
            <binding name="WS2007FederationHttpBinding_IService1">
                <security mode="TransportWithMessageCredential">
                    <message issuedKeyType="BearerKey" issuedTokenType="">
                        <tokenRequestParameters>
                            <trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
                                <trust:TokenType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</trust:TokenType>
                                <trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
                                <trust:CanonicalizationAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
                                <trust:EncryptionAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
                            </trust:SecondaryParameters>
                        </tokenRequestParameters>
                    </message>
                </security>
            </binding>
        </ws2007FederationHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:51853/Service1.svc" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
            name="BasicHttpBinding_IService1" />
        <endpoint address="https://localhost:44300/Service1.svc" binding="ws2007FederationHttpBinding"
            bindingConfiguration="WS2007FederationHttpBinding_IService1"
            contract="ServiceReference1.IService1" name="WS2007FederationHttpBinding_IService1" />
    </client>
  </system.serviceModel>

客户代码:

    static void Main(string[] args)
    {
        var factory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress("--Azure ACS URL omitted--"));
        factory.TrustVersion = TrustVersion.WSTrust13;
        factory.Credentials.UserName.UserName = "--omitted--";
        factory.Credentials.UserName.Password = "--omitted--";

        var rst = new RequestSecurityToken
        {
            RequestType = RequestTypes.Issue,
            KeyType = KeyTypes.Bearer,
            AppliesTo = new EndpointReference("https://localhost:44300/Service1.svc")
        };

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

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

        var factory2 = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:44300/Service1.svc"));
        factory2.Credentials.SupportInteractive = false;
        factory2.Credentials.UseIdentityConfiguration = true;

        var proxy = factory2.CreateChannelWithIssuedToken(token);

        var info = proxy.GetData("testing"); // Exception thrown here
    }

例外:

System.ServiceModel.Security.MessageSecurityException was unhandled
HResult=-2146233087
Message=An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.
Source=mscorlib
StackTrace:
  Server stack trace: 
   at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
   at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at TestWCFClient.ServiceReference1.IService1.GetData(String value)
   at TestWCFClient.Program.Main(String[] args) in c:\Users\nicole\Documents\Visual Studio 2012\Projects\TestWCFClient\Program.cs:line 43
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.ServiceModel.FaultException
   HResult=-2146233087
   Message=The message could not be processed. This is most likely because the action 'http://tempuri.org/IService1/GetData' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.
   InnerException: 

ETA: 此外,我尝试过:切换到SAML 2.0,使用预览JWT令牌处理程序切换到JWT,更改接收超时,将主机时间切换为UTC,显式同步主机与Windows时间服务,等待令牌发出后五分钟使用它。

1 个答案:

答案 0 :(得分:1)

MessageSecurityException是正确的:这是一个绑定错误。

我将几个代码示例混合在一起,并因错配而受到了攻击。 EstablishSecurityContext不仅仅是装饰窗口,它是绑定的真正部分,值必须在服务和客户端之间匹配。

我的应用程序代码为:

    var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
    binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
    binding.Security.Message.EstablishSecurityContext = false;  // this line is the problem

服务绑定是:

<bindings>
  <ws2007FederationHttpBinding>
    <binding name="">
      <security mode="TransportWithMessageCredential">
        <message issuedKeyType="BearerKey" issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"/> <!-- this line does not match -->
      </security>
    </binding>
  </ws2007FederationHttpBinding>
</bindings>

服务绑定应该是:

<bindings>
  <ws2007FederationHttpBinding>
    <binding name="">
      <security mode="TransportWithMessageCredential">
        <message issuedKeyType="BearerKey" establishSecurityContext="false"/> 
      </security>
    </binding>
  </ws2007FederationHttpBinding>
</bindings>

而且,它有效。