none
请问WCF如何进行安全认证后运行WCF的服务? RRS feed

  • 问题

  • 我现在有个疑问就是我发布WCF服务后,我如何确保别人无法引用我的WCF服务? 我看到有用509证书,还有用户密码的。如果用用户名和密码的话,我想最多是在使用前做一个认证吧,关于WCF中某个服务直接引用的话还是可以直接获取数据的。有没有什么方法可以让使用WCF服务前必须经过用户名和密码的认证后才能使用? 谢谢!
    2009年7月29日 1:58

答案

全部回复

  • 我现在有个疑问就是我发布WCF服务后,我如何确保别人无法引用我的WCF服务?我看到有用509证书,还有用户密码的。如果用用户名和密码的话,我想最多是在使用前做一个认证吧,关于WCF中某个服务直接引用的话还是可以直接获取数据的。有没有什么方法可以让使用WCF服务前必须经过用户名和密码的认证后才能使用?谢谢!

    Hi,
       欢迎来WCF中文技术论坛~
       我想确认一下你的问题:你的意思是说限制用户访问WCF元数据?还是限制用户调用WCF服务?
    Frank.Xu Lei--谦卑若愚,好学若饥

    Frank Xu Lei--谦卑若愚,好学若饥
    [老徐的网站]:http://www.frankxulei.com/

    [老徐的博客]:http://54peixun.com/Author/frankxulei
    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛


    2009年7月29日 3:41
    版主
  • 我是想限制用户调用,因为在VS2008中不是可以添加WEB服务的吗?然后把SVC路径放上去后就能调用了。我就是想限制这里的调用。
    谢谢版主回答!
    2009年7月29日 3:48
  • 我是想限制用户调用,因为在VS2008中不是可以添加WEB服务的吗?然后把SVC路径放上去后就能调用了。我就是想限制这里的调用。
    谢谢版主回答!


    Hi,
      不要客气。呵呵,我尽量回答你的问题。
      那你这个就属于在调用之前对客户端做出的验证。也就是客户端身份验证。WCF提供了多种方式来实现客户端身份验证。
    (1)匿名调用方。(None,也就是不验证,默认就是);

    (2)用户名客户端凭据:UserNamePassword验证方式,需要客户端提供正确的用户名和密码,服务端实现验证的类System.IdentityModel.Selectors.UserNamePasswordValidator ,重写Validate方法,在这里进行比较,错误的话可以抛出一个异常。

    (3)证书客户端凭据。:X509CertificateValidator ,重写Validate方法,对比客户端提供的证书,是不是正确的。

    (4)Windows(Kerberos 协议和 NT LanMan [NTLM]):Windows 集成身份验证,借助Windows 域账号实现安全验证,需要AD活动目录支持,适用企业局域网。
      
       这里是MSDN的官方文档:http://msdn.microsoft.com/zh-cn/library/ms730301.aspx,讲解了几乎所有的WCF安全验证方式。
      有点简略,可能你理解有困难。
      此外在给你一些建议:
      如果你仅仅个人学习,建议使用UserNamePassword方式,或者X509CertificateValidator 。这两个相对来说实现简单。
     WCF的安全级别已经提升,要求使用了安全验证必须提供证书支持。
      UserNamePassword验证方式,我个人也花了一段时间搞定,准备最近出个文章,给出可运行的代码给大家参考。
      网上很多资料,你也可以搜索。
      需要注意的就是证书 的制作和安装会出问题,你要注意。很多文章都没讲解。
       此论坛也有 关于安全和证书的更多讨论:
    http://social.microsoft.com/Forums/zh-CN/wcfzhchs/thread/34f10b1a-dede-4e4c-aa35-25fb4a655185
    http://social.microsoft.com/Forums/zh-CN/wcfzhchs/thread/9a525136-fae1-4abb-933c-8da89654509e


    Frank.Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    老徐的博客:http://frank_xl.cnblogs.com
    2009年7月29日 5:03
    版主
  • 我按你的方法做了,但是在CONFIG中好像配置不好。总是出现问题,配置如下:
    <bindings>
            <basicHttpBinding>
              <binding name="mySecureBinding">
                <security mode="Message">
                  <transport clientCredentialType="Basic" proxyCredentialType="None" realm=""/>
                  <message clientCredentialType="UserName" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/>
                </security>
              </binding>
            </basicHttpBinding>
          </bindings>

    错误:
    BasicHttp 绑定要求 BasicHttpBinding.Security.Message.ClientCredentialType 等效于安全消息的 BasicHttpMessageCredentialType.Certificate 凭据类型。为 UserName 凭据选择 Transport 或 TransportWithMessageCredential 安全性。

    我把<security mode>换成"Transport"又是另一种错误了,请问这里要如何配置?
    2009年7月29日 6:49
  • 我按你的方法做了,但是在CONFIG中好像配置不好。总是出现问题,配置如下:
    <bindings>
            <basicHttpBinding>
              <binding name="mySecureBinding">
                <security mode="Message">
                  <transport clientCredentialType="Basic" proxyCredentialType="None" realm=""/>
                  <message clientCredentialType="UserName" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/>
                </security>
              </binding>
            </basicHttpBinding>
          </bindings>

    错误:
    BasicHttp 绑定要求 BasicHttpBinding.Security.Message.ClientCredentialType 等效于安全消息的 BasicHttpMessageCredentialType.Certificate 凭据类型。为 UserName 凭据选择 Transport 或 TransportWithMessageCredential 安全性。

    我把<security mode>换成"Transport"又是另一种错误了,请问这里要如何配置?

    Hi,
       把 绑定协议的安全配置替换一下,不要传输安全。
    <binding  name="mySecureBinding"   >
              <security  mode="Message">
                <transport clientCredentialType="None"/>
                <message clientCredentialType="UserName"/>
              </security>
     </binding>

    Frank.Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    老徐的博客:http://frank_xl.cnblogs.com
    2009年7月29日 9:59
    版主
  • 版 主,按你说的改了,但是现在又出现错误“The service certificate is not provided. Specify a service certificate in ServiceCredentials. ”

    服务端WEBCONFIG:
    <bindings>
            <wsHttpBinding>
              <binding name="mySecureBinding">
                <security mode="Message">
                  <transport clientCredentialType="None"/>
                  <message clientCredentialType="UserName" />
                </security>
              </binding>
            </wsHttpBinding>
          </bindings>

    <behaviors>
           <serviceBehaviors>
              <behavior name="metadataSupport">
                <serviceCredentials>
                    <userNameAuthentication userNamePasswordValidationMode="Custom"
                       customUserNamePasswordValidatorType="SR.Service.SecurityValidatorService, SR.Service" />
                 </serviceCredentials>
              </behavior>
           </serviceBehaviors>
        </behaviors>



    客户端:
    <bindings>
          <wsHttpBinding><!--maxBufferSize="2147483647"-->
            <binding name="WSHttpBinding_Service" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
             maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transactionFlow="True" useDefaultWebProxy="true">
              <readerQuotas maxDepth="32" maxStringContentLength="512000" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
              <security mode="Message">
                <transport clientCredentialType="None"  />
                <message clientCredentialType="UserName" />
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>


    您能否帮我看一下哪里写的不对?谢谢!
    2009年7月30日 1:44
  • Hi,
        错误信息提示的对啊,就是你没有提供证书。
    1.制作一个证书:
    制作证书:
    Microsoft Visual Studio 2008-->Visual Studio Tools-->Visual Studio 2008 命令提示行里输入:
    makecert -r -pe -n "CN=FrankWCFServer" -ss My -sky exchange
    2.设置一个证书:
    设置证书:在WCF服务的配置文件里,设置对应的证书。直接在WCF服务端证书节点里添加如下代码即可:
     <serviceCertificate  x509FindType="FindBySubjectName" findValue="FrankWCFServer" storeLocation="CurrentUser"/>
    参考配置代码:
    services>
          
    <service behaviorConfiguration="WCFService.WCFServiceBehavior"
            name
    ="WCFService.WCFService">
            
    <endpoint 
              address
    ="http://localhost:8001/WCFService" 
              binding
    ="wsHttpBinding"  bindingConfiguration="MessageAndUserName" contract="WCFService.IWCFService">
            
    </endpoint>
            
            
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            
    <host>
              
    <baseAddresses>
                
    <add baseAddress="http://localhost:8002/"/>
              
    </baseAddresses>
            
    </host>
          
    </service>
        
    </services>
        
    <behaviors>
          
    <serviceBehaviors>
            
    <behavior name="WCFService.WCFServiceBehavior">
              
    <serviceMetadata httpGetEnabled="true" />
              
    <serviceDebug includeExceptionDetailInFaults="false" />
              
    <serviceCredentials>
                
    <serviceCertificate  x509FindType="FindBySubjectName" findValue="MyServer" storeLocation="CurrentUser"/>
                
                
    <clientCertificate >
                  
    <authentication certificateValidationMode="None"  />
                
    </clientCertificate>
                
    <userNameAuthentication userNamePasswordValidationMode="Custom"    customUserNamePasswordValidatorType="WCFService.MyUserNamePasswordValidator,WCFService" />
              
    </serviceCredentials>
            
    </behavior>
           
          
    </serviceBehaviors>
        
    </behaviors>
        
    <bindings>
          
    <wsHttpBinding>
            
    <binding  name="MessageAndUserName"   >
              
    <security >
                
    <message clientCredentialType="UserName"/>
              
    </security>
            
    </binding>
          
    </wsHttpBinding>
        
    </bindings>
         
    </system.serviceModel> 
    3.把证书设置为可信任的证书:
    你参考一下我的这个文章:WCF分布式开发常见错误(22):The caller was not authenticated...如何在XP系统为WCF设置可信任的证书
    这里讲解了如何制作一个证书,
        以上三步很关键,不然即使你制作了证书,但是没有提供设置也会出错。即使设置完毕,有可能还有别的错误,还需要设置证书为可信任。
    这样一个WCF安全的例子才会成功运行。
    Frank.Xu Lei--谦卑若愚,好学若饥

    Frank Xu Lei--谦卑若愚,好学若饥
    [老徐的网站]:http://www.frankxulei.com/

    [老徐的博客]:http://54peixun.com/Author/frankxulei
    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛


    2009年7月30日 4:23
    版主
  • 有问题继续讨论,我近期会出关于WCF安全开发文章,会放出代码~


    Frank.Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成

    Frank Xu Lei--谦卑若愚,好学若饥
    [老徐的网站]:http://www.frankxulei.com/

    [老徐的博客]:http://54peixun.com/Author/frankxulei
    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛


    2009年7月30日 4:49
    版主
  • 版主,我有个问题,如果用VS2008工具生成的证书可以随软件一起发布给客户使用吗?
    还有,是不是一定要有一个证书才可以?有没有不用证书就可以的?我本以前是只要判断一下用户名和密码就可以了,而且在WEBCONFIG中也这样设置的,但不知道还是要和证书联系起来。
    2009年7月30日 5:15
  • 版主,我有个问题,如果用VS2008工具生成的证书可以随软件一起发布给客户使用吗?
    还有,是不是一定要有一个证书才可以?有没有不用证书就可以的?我本以前是只要判断一下用户名和密码就可以了,而且在WEBCONFIG中也这样设置的,但不知道还是要和证书联系起来。
           

    Hi,

    更新补充一下:

    WCF发布后,只允许授权用户调用,WCF显然是支持的。也就是身份验证。

    a.元数据终结点如果你不想别人知道可以开发完毕后关闭。

    b.WCF支持多种身份验证方式。最简单的UserName和Password方式。

    你可以参考 这些文章。

    c.我也在写一个文章+例子,就是不用证书,原始的UserName和Password方式。请你关注我的博客http://www.54peixun.com/Author/frankxulei

    1)
       可以使用,证书,只是非对称加密算法的一个包装而已。这里如果仅仅满足最低要求,就是只在服务端安装证书,客户端添加服务引用,会获取服务端证书的公钥。客户端实际值使用公钥加密。
       不论你使用什么工具制作的证书,应该都符合一定的规范的,你说的工具应该就是makecert。
       它完全符合X.509证书的规范要求。你可以查看证书信息看看。
        你要是和软件一起发布,要注意的问题就是:
      a.证书到导出,最好私钥和公钥一起导出,然后你在服务器在进行安装。
      b.服务器上一样要设置证书为可信任的证书。不然服务会无法启动。
      c.这里只能保证客户端发送的消息,经过公钥加密以后,只有服务器能够解密。
      d.服务器证书安装以后,这个证书文件要销毁,如果泄露的话,基本等于没有加密。避免证书外泄。
     2)
       Web Service和WSE都允许这样,但是WCF不可以,主要原因就是WCF的安全直接提升了一个层次,使用WS-Secrity规范。这里核心就是X.509证书加密消息。也就是WCF强制支持WS-Security规范的话,无论服务器还是客户端通信,就必须使用证书。
       要么不使用安全,即:none.一旦使用,必须要求至少服务端,提供一个证书。
       WCF因为是面向服务的程序,所以对信息安全的要求就比较高,它基于的假设就是如果消息是不安全的,因为一旦被截获,就可以破译,这个等于安全形同虚设。任何人都可以冒充客户端发送消息。
    此外目前我所知道的不需要证书的安全策略是基于Windows 域账号的,这个针对的是企业内部局域网。





    Frank.Xu Lei--谦卑若愚,好学若饥

    Frank Xu Lei--谦卑若愚,好学若饥
    [老徐的网站]:http://www.frankxulei.com/

    [老徐的博客]:http://54peixun.com/Author/frankxulei
    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛



    2009年7月30日 8:42
    版主
  • 您好,我发布WCF服务一个星期也没搞定,看了你的回复差不多可以解决问题了

    我的操作步骤是这样的

    1 建立一个Console程序,WCFServer

    2、添加一个WCF WCFServer

    3、在Main中代码如下

    public static ServiceHost host = new ServiceHost(typeof(WCFServer));

    ...

     host.Open(new TimeSpan(0, 0, 1));

    4 、运行程序测试……通过,可以启动WCF服务

    5、创建、安装证书,makecert -r -pe -n "CN=zsw" -ss My -sky exchange

    5、按照提示,修改了配置文件,修改后的配置文件如下

     <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="WCFServer.WCFServerBehavior">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="false" />
             
              <serviceCredentials>
                <serviceCertificate  x509FindType="FindBySubjectName" findValue="zsw" storeLocation="CurrentUser"/>

                <clientCertificate >
                  <authentication certificateValidationMode="None"  />
                </clientCertificate>
                <userNameAuthentication userNamePasswordValidationMode="Custom"    customUserNamePasswordValidatorType="WCFService.MyUserNamePasswordValidator,WCFService" />
              </serviceCredentials>

            </behavior>
           
          </serviceBehaviors>
         
        </behaviors>
        <services>
          <service behaviorConfiguration="WCFServer.WCFServerBehavior"
            name="WCFServer.WCFServer">
            <endpoint address="http://localhost:4616/WCFService" bindingConfiguration="MessageAndUserName" binding="wsHttpBinding" contract="WCFServer.IWCFServer">
              <identity>
                <dns value="localhost" />
              </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:4243/WCFServer/" />
              </baseAddresses>
            </host>
          </service>
        </services>
        <bindings>
          <wsHttpBinding>
            <binding  name="MessageAndUserName"   >
              <security >
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>  </system.serviceModel>

    修改后运行服务端程序出错,服务不能启动,错误为


    未处理的异常:  System.TypeInitializationException: “WCFServer.Program”的类型初始值设定项引发异常。 ---> System.IO.FileNotFoundException: 未能加载文件或程序集“WCFService”或它的某一个依赖项。系统找不到指定的文件。
    文件名:“WCFService”   在 System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, tackCrawlMark& stackMark, Boolean loadTypeFromPartialName)

    ...

    请问怎么回事啊

     

    2010年5月17日 3:07