【问题标题】:MessageSecurityException with ACS issued token and WIFACS 颁发的令牌和 WIF 的 MessageSecurityException
【发布时间】:2013-04-27 05:14:34
【问题描述】:

我正在使用 ACS/Service Identities 作为临时 STS,而我正在准备就绪。不幸的是,虽然我似乎能够从 ACS 获得 SAML 1.1 令牌,但当我尝试将它传递到我的 WCF 服务时,事情变得疯狂。据我所知,令牌没有过期(它正在被及时使用),我不确定它怎么可能是无效的,而且我所做的任何日志记录都没有向我显示任何关于确切可能是什么的细节错误的。我很想将责任归咎于绑定,因为我以前从未做过正式的 WCF/WIF 绑定。任何人都可以看到我正在使用的客户端/服务器绑定有什么问题(客户端是通过服务引用生成的),或者建议另一种调查途径?

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

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: 

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

【问题讨论】:

  • 对我来说,您似乎两次调用相同的 sts 服务(端口 44300),而第二次似乎应该转到 51853。如果这是正确答案,请告诉我。
  • 第一个请求将发送到我的 Azure ACS 命名空间,即我的临时 STS;我可以理解它可能令人困惑的地方。我只是请求一个与本地主机 URL 匹配的领域的令牌。它绝对不应该转到 51853,因为如果是这样,我将通过不安全的传输方式发送安全令牌。
  • 我的意思是第二个请求,而不是第一个。与 factory2 的 ine。
  • localhost:44300/Service1.svc 不是 STS。这是需要令牌的服务。
  • 我现在明白了。抱歉提供误导性线索。那么 51853 是什么?

标签: wcf wif


【解决方案1】:

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

我将几个代码示例混合在一起,结果不匹配。建立安全上下文不只是装点门面,它是真正的绑定部分,服务和客户端的值必须匹配。

我的应用程序代码如下:

    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>

而且很快,它就起作用了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-03
    • 2016-02-02
    • 2013-10-11
    • 1970-01-01
    • 2016-01-28
    • 2019-05-02
    • 1970-01-01
    • 2015-02-10
    相关资源
    最近更新 更多