2011-07-05 9 views
7

내 특정 문제는이 같은 것입니다 : 우리는 현재를 호출 할 때 인증과 같은 사용자 이름과 암호를 제공하기 위해 클라이언트를 필요로 일련의 서비스를 실행하는사용자 정의 클라이언트 인증서와 사용자 이름 검증

  • 서비스.

  • 우리는 이러한 서비스에 PKI 인프라를 구현하고자하지만 파트너 중 일부는 다른 인프라보다이 새로운 인프라를 수용하는 데 더 많은 시간을 사용할 것입니다.

  • 첫 번째 단계로 일부 파트너의 클라이언트 인증서가 필요합니다. 다른 사용자의 경우 사용자 이름과 암호 만 필요하지만 서버의 데이터에 액세스하려면 클라이언트 인증서가 필요합니다 (사용자 이름과 암호 이외에).

내가 사용자 이름/암호 인증 (UserNamePasswordValidator 사용)와 WCF에서 (X509CertificateValidator 사용) 클라이언트 인증서 모두에 대한 사용자 지정 유효성 검사기를 구현하기 위해 노력하고이 문제를 해결합니다. 사용자 이름/암호 검사기는 데이터베이스에 대해 이러한 자격 증명을 확인하고 클라이언트 인증서 유효성 검사기는 요청이 우리가 인증서를 요구하는 클라이언트에서 왔는지 여부를 검사하고, 그렇다면 유효한 클라이언트 인증서가 제공되는지 확인합니다. 이 두 가지 유효성 검사기를 모두 사용하도록 WCF를 구성 할 수 없었습니다.

서버 내 WCF 구성은 현재 다음과 같이 설정되어

:

<behaviors> 
    <serviceBehaviors> 
    <behavior name="MyServiceBehavior"> 
     <serviceMetadata httpsGetEnabled="true" policyVersion="Policy15" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
     <serviceCredentials> 
     <clientCertificate> 
      <authentication customCertificateValidatorType="MyWS.Security.MyServicesCertificateValidator, MyWS" 
      certificateValidationMode="Custom" revocationMode="NoCheck" /> 
     </clientCertificate> 
     <userNameAuthentication userNamePasswordValidationMode="Custom" 
      customUserNamePasswordValidatorType="MyWS.Security.MyServicesUsernameValidator, MyWS" /> 
     </serviceCredentials> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/> 
<bindings> 
    <basicHttpBinding> 
    <binding name="MySoapBinding"> 
     <security mode="TransportWithMessageCredential"> 
     <transport clientCredentialType="Certificate" /> 
     <message clientCredentialType="UserName" /> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<services> 
    <service behaviorConfiguration="MyServiceBehavior" name="MyWS.Services.TheService"> 
    <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MySoapBinding" name="TheService" bindingNamespace="https://services.my/TheService" contract="MyWS.Interfaces.Service.ITheService" /> 
    <host> 
     <baseAddresses> 
     <add baseAddress="https://localhost:4434/MyWS/TheService"/> 
     </baseAddresses> 
    </host> 
    </service> 
</services> 

지금까지 내가 IIS가를 검사하기 때문에 내가 (전송 계층에서 customCertificateValidatorType를 사용하지 못할 때문에이 구성이 유효하지 않습니다 이해 인증서를 WCF 전에 여기에 관여)하지만 메시지 레이어에서 customCertificateValidatorType 및 customUserNamePasswordValidatorType을 자격 증명 유형으로 결합 할 수있는 방법을 확인할 수 없습니다.

메시지 관리자를 구현했으며 (아래 링크에서 제안 된 것처럼) 어떤 방식 으로든 OperationContext를 사용하여 문제를 해결할 수는 있지만, 이렇게 할 수있는 방법을 볼 수 없었습니다. 아직 ... 내가 WCF의 작동 방식과 호환되지 않는 무언가를 구현하려고 할 수도 있지만, 누군가가이 해결 될 수있는 방법에 대한 아이디어가 있다면 내가 가진 기뻐할 것입니다 가정

http://social.msdn.microsoft.com/Forums/en/wcf/thread/b6ab8b58-516b-41d4-bb0e-75b4baf92716

당신의 이것에 대한 피드백!

답변

6

나는 그의 대답에서 @ ladislav-mrnka의 귀중한 입력 덕분에 내 문제에 대한 해결책을 발견했다고 생각합니다. 서로 다른 요구 사항을 구성하기 위해 두 개의 끝점을 제공해야한다는 것을 깨달았으며 서비스를 구성 할 때 토큰 가능성을 지원하는 방법에 대해서도 배웠습니다.

MSDN에서 supporting tokens에 대한 링크를 발견했으며이 레서피를 수행하여 다음 사용자 정의 바인딩이있는 서버에서 엔드 포인트를 구현했습니다. (코드를 통해 구성으로 전환했습니다. 웹에이 메시지가 설정되어 있는지 확실하지 않습니다. 뿐만 아니라 설정.)

private static Binding CreateMultiFactorAuthenticationBinding() 
{ 
    var httpsTransport = new HttpsTransportBindingElement(); 

    // The message security binding element will be configured to require 2 tokens: 
    // 1) A username-password encrypted with the service token 
    // 2) A client certificate used to sign the message 

    // Create symmetric security binding element with encrypted username-password token. 
    // Symmetric key is encrypted with server certificate. 
    var messageSecurity = SecurityBindingElement.CreateUserNameForCertificateBindingElement(); 
    messageSecurity.AllowInsecureTransport = false; 

    // Require client certificate as endorsing supporting token for all requests from client to server 
    var clientX509SupportingTokenParameters = new X509SecurityTokenParameters 
                { 
                 InclusionMode = 
                  SecurityTokenInclusionMode.AlwaysToRecipient 
                }; 
    messageSecurity.EndpointSupportingTokenParameters.Endorsing.Add(clientX509SupportingTokenParameters); 

    return new CustomBinding(messageSecurity, httpsTransport); 
} 

이 바인딩은 서버 인증서로 암호화 대칭 키() 메시지 헤더에 사용자 이름/암호 보안 토큰을 암호화하는 데 사용되는 SymmetricSecurityBindingElement를 생성하고, 메시지 본문 자체.

또한 X509 보안 토큰이 토큰을 바인딩에 지원하는 승인으로 추가됩니다. 이 토큰은 클라이언트 요청에 항상 포함되도록 구성됩니다.

이 사용자 지정 바인딩은 이후에이 바인딩이 필요한 끝점을 사용하여 새 WCF 서비스를 구성하는 데 사용되었습니다. Castle Windsor의 WcfFacility를 사용하여 서비스를 구성하고 있습니다.

이 코드는 다음을

  • 들어오는 클라이언트 인증서가 신뢰할 수있는 루트 인증 기관에서 발급 한 것이어야합니다 있도록
  • 는, 체인의 신뢰에 클라이언트 인증서의 유효성 확인 모드를 설정 서비스 인증서를 설정합니다 서버 저장소는
  • 는 사용자 이름/암호 인증 및 클라이언트 인증서
//// Registering WCF-services 
var returnFaults = new ServiceDebugBehavior {IncludeExceptionDetailInFaults = true}; 
var metaData = new ServiceMetadataBehavior {HttpsGetEnabled = true}; 

var serviceCredentials = new ServiceCredentials(); 

// Configure service sertificate 
serviceCredentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine, 
    StoreName.My, 
    X509FindType.FindBySubjectName, 
    "ServerCertificate"); 

// Configure client certificate authentication mode 
serviceCredentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.ChainTrust; 

// Add custom username-password validator 
serviceCredentials.UserNameAuthentication.UserNamePasswordValidationMode = 
    UserNamePasswordValidationMode.Custom; 
serviceCredentials.UserNameAuthentication.CustomUserNamePasswordValidator = 
    _container.Resolve<MyServicesUsernameValidator>(); 

// Add custom certificate validator 
serviceCredentials.ClientCertificate.Authentication.CertificateValidationMode = 
    X509CertificateValidationMode.Custom; 
serviceCredentials.ClientCertificate.Authentication.CustomCertificateValidator = 
    _container.Resolve<MyServicesCertificateValidator>(); 

var serviceModel = new DefaultServiceModel(); 

serviceModel.AddEndpoints(
    WcfEndpoint.ForContract<IMyContract>().BoundTo(CreateMultiFactorAuthenticationBinding())); 
serviceModel.BaseAddresses.Add(new Uri("https://server.com/MyServiceImplementation.svc")); 

serviceModel.AddExtensions(serviceCredentials); 
serviceModel.AddExtensions(metaData); 

_container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero) 
    .Register(Component.For<IMyContract>() 
        .ImplementedBy<MyServiceImplementation>() 
        .AsWcfService(serviceModel), 
       Component.For<IServiceBehavior>().Instance(returnFaults)); 
,536,913에 대한 사용자 지정 유효성 검사기를 추가

MyServicesUsernameValidator는 UserNamePasswordValidator를 상속하고 MyServicesCertificateValidator는 X509CertificateValidator를 상속합니다. 둘 다 해당하는 Validate 메소드를 대체합니다.

이것은 내 특별한 문제를 해결하는 것 같습니다 ... 희망이 당신을 해결합니다! :)

4

기본적으로 상자 바인딩이있는 구성에서는 정의 할 수 없습니다. 사용자 지정 Y 인딩조차도 구성에서 이러한 Y 인딩을 정의하기에 충분한 인프라를 지원하지 않습니다.

먼저 두 개의 종단점이 필요합니다. 하나는 사용자 이름/암호가있는 클라이언트에만 사용됩니다. 이 끝점은 UserName 클라이언트 자격 증명이있는 메시지 보안 또는 메시지 자격 증명이있는 전송 보안 중 하나를 예상하는 일부 공용 바인딩을 사용하여 구성 할 수 있습니다. 두 번째 끝점은보다 복잡한 유효성 검사를위한 것입니다. 이 엔드 포인트는 코드에 정의 된 새로운 바인딩을 필요로합니다. 이 사용해야합니다 바인딩 :

  • 비대칭 보안 바인딩 요소 (상호 인증서 인증)
  • X를토큰 (509)의 보안 토큰과 같은 기본 보안

이 I 유사한 서비스와 통신 할 때 사용했던 결합의 예는 토큰 보안을 지원하는 것으로

  • 사용자 이름 보안 토큰 :

    Custom binding = new CustomBinding(); 
        var userNameToken = new UserNameSecurityTokenParameters(); 
        userNameToken.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient; 
    
        var securityElement = new AsymmetricSecurityBindingElement(); 
        securityElement.IncludeTimestamp = true; 
        securityElement.RecipientTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.SubjectKeyIdentifier, SecurityTokenInclusionMode.Never); 
        securityElement.InitiatorTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.SubjectKeyIdentifier, SecurityTokenInclusionMode.AlwaysToRecipient); 
        securityElement.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256; 
        securityElement.SecurityHeaderLayout = SecurityHeaderLayout.Strict; 
        securityElement.SetKeyDerivation(false); 
        securityElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(userNameToken); 
        securityElement.MessageProtectionOrder = MessageProtectionOrder.EncryptBeforeSign; 
        securityElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11; 
        binding.Elements.Add(securityElement); 
    
        var encodingElement = new TextMessageEncodingBindingElement(); 
        encodingElement.MessageVersion = MessageVersion.Soap12WSAddressingAugust2004; 
        binding.Elements.Add(encodingElement); 
    
        var httpElement = new HttpTransportBindingElement(); 
        httpElement.UseDefaultWebProxy = true; 
        binding.Elements.Add(httpElement); 
    

    이 예 용도 코드에 CustomBinding이 정의되어 있습니다. 구성에서이 기능을 사용하려면 완전히 새로운 바인딩 및 바인딩 확장을 생성하고 해당 확장을 구성 파일에 등록해야합니다.

    그렇다면 두 가지 유효성 검사기가 모두 사용 될지 잘 모르겠습니다. 서비스의 클라이언트로 사용했습니다. 주요 요점은 요청에 단 하나의 기본 토큰 만있을 수 있으며 기본 WCF 인프라가 유효성을 검사하기 위해 하나만 선택하는 것이 가능하지만 그러한 논리도 대체 될 수 있다는 것입니다.

  • +0

    의견을 보내 주셔서 감사합니다. 그것은 올바른 방향으로 나를 인도 해주었습니다. 여러 끝점을 사용하고 사용자 지정 바인딩에서 토큰을 지원했습니다. – Hanskun

    관련 문제