1

아래 코드는 Silverlight 4 클라이언트 (아래 코드 참조)에 서비스를 제공해야하는 사용자 지정 인증 WCF 서비스를 사용하여 자체 호스팅 된 을 실행한다고 가정합니다.자체 호스팅 WCF + 사용자 지정 UserNamePasswordValidator + Silverlight 4

결과적으로 clientaccesspolicy.xml이 브라우저에 표시되고 SSL 오류가 표시되지 않지만 악의적 인 clientaccesspolicy 보안 오류 통신 예외는 으로 표시됩니다. clientaccesspolicy.xml 중단 점이 적중되지 않습니다.

내가 항목을 지정해야한다는 것을 알았지 만 시도했습니다. clientaccesspolicy.xml과 함께 다양한 게임이 작동하지 않았습니다.

<?xml version="1.0"?> 
<configuration> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
    </startup> 
    <system.serviceModel> 
    <client /> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="slBindingWithUserNamePassValidator"> 
      <security mode="TransportWithMessageCredential"> 
      <message clientCredentialType="UserName" /> 
      </security> 
     </binding> 
     </basicHttpBinding> 
     <webHttpBinding> 
     <binding name="capService" crossDomainScriptAccessEnabled="true"> 
      <security mode="Transport" /> 
     </binding> 
     <binding name="capServiceNoSSL" crossDomainScriptAccessEnabled="true"> 
      <security mode="None" /> 
     </binding> 
     </webHttpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="svcBehavior" name="WCF_Self_Hosted_UserName_Validator.Service1"> 
     <endpoint address="" binding="webHttpBinding" bindingConfiguration="capService" behaviorConfiguration="capServiceBehavior" 
      contract="WCF_Self_Hosted_UserName_Validator.ICAPService" /> 
     <endpoint address="" binding="webHttpBinding" bindingConfiguration="capServiceNoSSL" behaviorConfiguration="capServiceBehavior" 
      contract="WCF_Self_Hosted_UserName_Validator.ICAPService" /> 
     <endpoint address="MyCustomValidationService" binding="basicHttpBinding" bindingConfiguration="slBindingWithUserNamePassValidator" 
      contract="WCF_Self_Hosted_UserName_Validator.IService1"> 
     </endpoint> 
     <host> 
      <baseAddresses> 
      <add baseAddress="https://(somesite):9999/" /> 
      <add baseAddress="http://(somesite):9998/" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="svcBehavior"> 
      <serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
     <endpointBehaviors> 
     <behavior name="capServiceBehavior"> 
      <webHttp/> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel> 
</configuration> 

서비스에 대한 코드 :

Using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Security.Cryptography.X509Certificates; 
using System.ServiceModel; 
using System.IdentityModel.Selectors; 
using System.IO; 
using System.ServiceModel.Web; 

namespace WCF_Self_Hosted_UserName_Validator 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyServiceHost host = new MyServiceHost(new Service1()); 
      host.Open(); 
      Console.WriteLine("Host open..."); 
      Console.ReadLine(); 
     } 

    } 
    public class MyServiceHost : ServiceHost 
    { 
     SecurityValidator _securityValidator = null; 
     public MyServiceHost(IService1 svc) : base(svc) 
     { 
      Credentials.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom; 
      _securityValidator = new SecurityValidator(); 
      Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = _securityValidator; 
      Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "my-fqdn-valid-cert.dot.something"); 
     } 
    } 
    public class SecurityValidator : UserNamePasswordValidator 
    { 
     public SecurityValidator() 
     { 
     } 
     public override void Validate(string userName, string password) 
     { 
      try 
      { 
       if (userName != "1" && password != "1") 
        throw new FaultException("auth error"); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 
    } 
    [ServiceContract] 
    public interface IService1 
    { 
     [OperationContract] 
     string GetPrivateInfo(); 
    } 
    [ServiceContract] 
    public interface ICAPService 
    { 
     [OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")] 
     Stream GetClientAccessPolicy(); 
    } 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
    public class Service1 : IService1, ICAPService 
    { 
     public string GetPrivateInfo() 
     { 
      return "Some info " + DateTime.Now.ToShortTimeString(); 
     } 
     public System.IO.Stream GetClientAccessPolicy() 
     { 
      WebOperationContext ctx = new WebOperationContext(OperationContext.Current); 
      string txtCap = @"<?xml version=""1.0"" encoding=""utf-8"" ?> 
<access-policy> 
    <cross-domain-access> 
     <policy> 
      <allow-from http-request-headers=""*""> 
       <domain uri=""*""/> 
       <domain uri=""http://*""/> 
       <domain uri=""https://*""/> 
      </allow-from> 
      <grant-to> 
       <resource include-subpaths=""true"" path=""/""/> 
      </grant-to> 
     </policy> 
    </cross-domain-access> 
</access-policy>"; 
      WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; 
      MemoryStream response = new MemoryStream(Encoding.UTF8.GetBytes(txtCap)); 
      return response; 
     } 
    } 
} 

2) 우리는이

당신의 도움이 서비스에 대한의 app.config 및 코드)

1

을 감사합니다 로컬 컴퓨터의 MY 컨테이너에있는 CA 서명 SSL 인증서 및 netsh 사용

netsh http add sslcert ipport=0.0.0.0:9999 certhash=aabbcc_thumbprint 
appid={my_app_id_guid} clientcertnegotiation=enable 

위가 성공적으로 실행되고 호스트가 올바르게로드되고 새 Silverlight 프로젝트를 만들 수 있습니다.

3) 실버 프로젝트는 추가 서비스 참조와 단지 새로운 silveright 프로젝트 및 다음 코드 :

namespace SilverlightApplication1 
{ 
    public partial class MainPage : UserControl 
    { 
     public MainPage() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, RoutedEventArgs e) 
     { 
      ServiceReference1.Service1Client c = new ServiceReference1.Service1Client(); 
      c.ClientCredentials.UserName.UserName = "1"; 
      c.ClientCredentials.UserName.Password = "1"; 
      c.GetPrivateInfoCompleted += new EventHandler<ServiceReference1.GetPrivateInfoCompletedEventArgs>(c_GetPrivateInfoCompleted); 
      c.GetPrivateInfoAsync(); 
     } 

     void c_GetPrivateInfoCompleted(object sender, ServiceReference1.GetPrivateInfoCompletedEventArgs e) 
     { 
      if (e.Error == null) 
      { 
       this.Content = new TextBlock() { Text = e.Result }; 
      } 
      else 
      { 
       this.Content = new TextBlock() { Text = e.Error.GetBaseException().Message }; 
      } 
     } 
    } 
} 

4) 이것은 ServiceReferences.ClientConfig이

<configuration> 
    <system.serviceModel> 
     <bindings> 
      <basicHttpBinding> 
       <binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647" 
        maxReceivedMessageSize="2147483647"> 
        <security mode="TransportWithMessageCredential" /> 
       </binding> 
      </basicHttpBinding> 
     </bindings> 
     <client> 
      <endpoint address="https://(TheAddress)/MyCustomValidationService" 
       binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" 
       contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" /> 
     </client> 
    </system.serviceModel> 
</configuration> 

답변

0

을 생성 Blockquote netsh http add sslcert ipport = 0.0.0.0 : 9999 certhash = aabbcc_thumbprint appid = {my_app_id_guid} clientcertnegotiation = enable

netsh에 clientcertnegotiation 플래그를 사용 했으므로 서버에 클라이언트 인증서가 필요합니다. Silverlight가 clientaccess 정책을 호출하면 클라이언트 인증서를 보내지 않으므로 예외가 발생합니다.

클라이언트 인증서가 필요하지 않은 경우이 플래그를 제거하십시오.

clientaccesspolicy를 가져올 때 SL이 클라이언트 인증서를 보낼 수 있는지 확실하지 않지만 웹 페이지에서도 해당 사이트에 액세스하는 경우 브라우저에서 제공 한 인증서를 사용해야합니다. 그래서 ucan u는 귀하의 호스팅 html/aspx에서 보안 사이트에 대한 링크를 추가하려고 시도합니다. 그러면 인증서를 선택해야하며 SL은 해당 인증서를 사용합니다.