2013-04-26 42 views
2

我正在使用ACS /服务标识作为临时STS,同时让事情到位。不幸的是,虽然我似乎能够从ACS获得SAML 1.1令牌,但第二次尝试将它传递给我的WCF服务时,事情变得很疯狂。据我所知,令牌没有过期(它正在被快速使用),我不确定它是如何失效的,而且我没有做过任何关于日志记录的信息,这些信息告诉我什么可能是什么细节错误。我很想将责任归咎于绑定,因为我之前从未做过正式的WCF/WIF绑定。任何人都可以看到我使用的客户端/服务器绑定有任何问题(客户端是通过服务引用生成的),还是提出了一个可供选择的调查途径?使用ACS颁发的令牌和WIF的MessageSecurityException

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

的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时间服务同步,并在使用令牌之后等待五分钟。

+0

对我来说,好像你正在调用同一个sts服务两次(端口44300),而它看起来像第二个应该去51853.让我知道这是否是一个正确的答案。 – 2013-04-26 18:28:14

+0

第一个请求将进入我的Azure ACS命名空间,即我的临时STS;我可以理解它可能会让人困惑的地方。我只需要一个具有与本地主机URL匹配的领域的令牌。它绝对不应该去51853,因为如果这样做,我会通过不安全的交通工具发送安全令牌。 – 2013-04-26 18:46:14

+0

我的意思是第二次请求,而不是第一次请求。与工厂2。 – 2013-04-26 18:54:54

回答

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> 

而且似的,它的工作原理。