WSTrustServiceHost.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System;
  7. using System.Collections.ObjectModel;
  8. using System.IdentityModel.Configuration;
  9. using System.ServiceModel;
  10. using System.ServiceModel.Channels;
  11. using System.ServiceModel.Description;
  12. using System.Web.Configuration;
  13. using System.Web.Hosting;
  14. /// <summary>
  15. /// ServiceHost for registering SecurityTokenService. The ServiceHost will have multiple endpoints
  16. /// registered based on the number of listeners registered in the config.
  17. /// </summary>
  18. public class WSTrustServiceHost : ServiceHost
  19. {
  20. WSTrustServiceContract _serviceContract;
  21. /// <summary>
  22. /// Initializes an instance of <see cref="WSTrustServiceHost"/>
  23. /// </summary>
  24. /// <param name="securityTokenServiceConfiguration">SecurityTokenServiceConfiguration instance used to initialize this ServiceHost.</param>
  25. /// <param name="baseAddresses">BaseAddress collection for the service host</param>
  26. /// <remarks>
  27. /// A default WSTrustServiceContract is instantiated using the SecurityTokenServiceConfiguration instance.
  28. /// The SecurityTokenServiceConfiguration instance is used for one-time initialization of the ServiceHost and
  29. /// setting properties on the configuration instance after the host is initialization may not result in
  30. /// behavioral changes.
  31. /// </remarks>
  32. public WSTrustServiceHost(SecurityTokenServiceConfiguration securityTokenServiceConfiguration, params Uri[] baseAddresses)
  33. : this(new WSTrustServiceContract(securityTokenServiceConfiguration), baseAddresses)
  34. {
  35. }
  36. /// <summary>
  37. /// Initializes an instance of <see cref="WSTrustServiceHost"/>
  38. /// </summary>
  39. /// <param name="serviceContract">ServiceContract implementation to use.</param>
  40. /// <param name="baseAddresses">BaseAddress collection for the service host</param>
  41. /// <exception cref="ArgumentNullException">One of the input argument is null.</exception>
  42. public WSTrustServiceHost(WSTrustServiceContract serviceContract, params Uri[] baseAddresses)
  43. : base(serviceContract, baseAddresses)
  44. {
  45. if (serviceContract == null)
  46. {
  47. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceContract");
  48. }
  49. if (serviceContract.SecurityTokenServiceConfiguration == null)
  50. {
  51. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceContract.SecurityTokenServiceConfiguration");
  52. }
  53. _serviceContract = serviceContract;
  54. }
  55. /// <summary>
  56. /// Gets the WSTrustServiceContract associated with this instance.
  57. /// </summary>
  58. public WSTrustServiceContract ServiceContract
  59. {
  60. get
  61. {
  62. return _serviceContract;
  63. }
  64. }
  65. /// <summary>
  66. /// Gets the SecurityTokenServiceConfiguration
  67. /// </summary>
  68. public SecurityTokenServiceConfiguration SecurityTokenServiceConfiguration
  69. {
  70. get
  71. {
  72. return _serviceContract.SecurityTokenServiceConfiguration;
  73. }
  74. }
  75. /// <summary>
  76. /// Configures metadata (WSDL) for the service host. The method loops through the
  77. /// base addresses, and adds mex endpoints for http, https, net.tcp and net.pipe
  78. /// addresses, only when no mex endpoints have been previously added by the user.
  79. /// For http and htps addresses, HTTP and HTTPS "Get" mechanism for WSDL retrieval
  80. /// is enabled.
  81. /// </summary>
  82. protected virtual void ConfigureMetadata()
  83. {
  84. if (this.BaseAddresses == null || this.BaseAddresses.Count == 0)
  85. {
  86. throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID3140));
  87. }
  88. // Check if a ServiceMetadataBehavior is added.
  89. ServiceMetadataBehavior metadataBehavior = Description.Behaviors.Find<ServiceMetadataBehavior>();
  90. if (metadataBehavior == null)
  91. {
  92. metadataBehavior = new ServiceMetadataBehavior();
  93. Description.Behaviors.Add(metadataBehavior);
  94. }
  95. // Check if an Mex endpoint has alread been added by user. This can be enabled through
  96. // configuration.
  97. bool isMexEndpointAlreadyAdded = (Description.Endpoints.Find(typeof(IMetadataExchange)) != null);
  98. Binding mexBinding = null;
  99. foreach (Uri baseAddress in this.BaseAddresses)
  100. {
  101. if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeHttp))
  102. {
  103. metadataBehavior.HttpGetEnabled = true;
  104. mexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
  105. }
  106. else if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeHttps))
  107. {
  108. metadataBehavior.HttpsGetEnabled = true;
  109. mexBinding = MetadataExchangeBindings.CreateMexHttpsBinding();
  110. }
  111. else if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeNetTcp))
  112. {
  113. mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
  114. }
  115. else if (StringComparer.OrdinalIgnoreCase.Equals(baseAddress.Scheme, Uri.UriSchemeNetPipe))
  116. {
  117. mexBinding = MetadataExchangeBindings.CreateMexNamedPipeBinding();
  118. }
  119. if (!isMexEndpointAlreadyAdded && (mexBinding != null))
  120. {
  121. AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, mexBinding, "mex");
  122. }
  123. mexBinding = null;
  124. }
  125. }
  126. /// <summary>
  127. /// Loads the service description information from the configuration file and
  128. /// applies it to the runtime being constructed.
  129. /// </summary>
  130. protected override void ApplyConfiguration()
  131. {
  132. base.ApplyConfiguration();
  133. //
  134. // Configure metadata endpoints
  135. //
  136. WSTrustServiceContract serviceContract = (WSTrustServiceContract)base.SingletonInstance;
  137. if (!serviceContract.SecurityTokenServiceConfiguration.DisableWsdl)
  138. {
  139. ConfigureMetadata();
  140. }
  141. }
  142. /// <summary>
  143. /// Override of the base class method. Configures the <see cref="ServiceConfiguration"/> on the
  144. /// service host and then invokes the base implementation.
  145. /// </summary>
  146. protected override void InitializeRuntime()
  147. {
  148. if (Description.Endpoints.Count == 0)
  149. {
  150. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID3097)));
  151. }
  152. UpdateServiceConfiguration();
  153. base.InitializeRuntime();
  154. }
  155. /// <summary>
  156. /// Overrides the <see cref="IdentityConfiguration"/> on the ServiceHost Credentials
  157. /// with the SecurityTokenServiceConfiguration.
  158. /// </summary>
  159. protected virtual void UpdateServiceConfiguration()
  160. {
  161. Credentials.IdentityConfiguration = _serviceContract.SecurityTokenServiceConfiguration;
  162. Credentials.UseIdentityConfiguration = true;
  163. }
  164. }
  165. }