通过netTcp的WCF自定义安全性

时间:2011-11-27 09:40:21

标签: wcf security net-tcp

我是WCF的新手,我正在制作服务器/客户端应用程序,我需要有一些用户/密码架构来维护每个客户端的一些自定义设置并记录谁访问该服务,但是“安全性”由于信息不敏感,因此不需要通过网络的流量。 所以考虑到这一点,我正在寻找一种简单的方法来实现这一点,但我找不到它。

我有一些约束和条件:

  • Windows安全性不是一种选择。
  • 我正在使用clickonce部署,因此应该包含所有内容 在安装包内。我不知道实际的用户列表 正在下载它,所以我没有办法分发一些 证书给所有用户。
  • 此外,客户端将在局域网内通过几个接入 广域网。必须满足的另一个要求是服务应该 由于每个数据流动很多,因此具有非常好的性能 回答,所以问题是:
  

邮件安全性是否会以极其糟糕的方式损害性能?

“手动”方式是将用户名作为我正在公开的每个方法的参数传递,但这似乎是一个非常脏的解决方案。

在我看来,设计这个有很多限制,所以我就是在问这个问题。

哪个是最简单的解决方案?

1 个答案:

答案 0 :(得分:2)

首先,我们必须假设所有使用该服务的用户都以某种方式“注册”以使用该服务。因为如果它是公开的,匿名的,那么根本就没有跟踪。所以我的假设如下:

  1. 该服务托管在Windows服务/ WinForms中以支持TCP 端点。 - 对于新版本的IIS(> 6),这不再是必需的假设
  2. 有一个像“UserName / Password”这样的组合进行身份验证。这个 不在活动目录中(不选择Windows身份验证) 但可能是xml / database。
  3. 我们不愿意使用像public int Add(string User, string Password, int A, int B)
  4. 这样的方法

    我有一个TCP端点的服务,它做了这样的事情。我会分享一下。我并不认为这是最好的做法。

    申请名称是MYAPP

    我提供了

    customUserNamePasswordValidatorType="MYAPPHost.Authenticate, MYAPPHost" 
    

    in

    serviceCredentials > userNameAuthentication 
    
    web.config的

    部分。

    MYAPPHost是我的Windows服务的名称。 Authenticate是从数据库进行身份验证的类。

    message clientCredentialType="UserName"设置为TCPBinding。

    我的Windows服务的App.Config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.diagnostics>
        <sources>
          <source name="System.ServiceModel"
              switchValue="Off" propagateActivity="true" >
            <listeners>
              <add name="SERVICE_MONITOR" type="System.Diagnostics.XmlWriterTraceListener"
                   initializeData="MYAPP_MONITOR.svclog" />
            </listeners>
          </source>      
          <source name="MYAPP_TRACE" switchValue="All" >
            <listeners>
              <add name="MYAPP_TRACE_LISTENER" type="System.Diagnostics.XmlWriterTraceListener"                                         
                   initializeData="MYAPP_TRACE.svclog" />
            </listeners>
          </source>
        </sources>
        <trace autoflush="true" />
      </system.diagnostics> 
    
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="OverAllServiceBehavior">
              <serviceSecurityAudit 
                auditLogLocation="Application" 
                serviceAuthorizationAuditLevel="Failure" 
                messageAuthenticationAuditLevel="Failure" 
                suppressAuditFailure="true" />          
              <serviceDebug includeExceptionDetailInFaults="True" />
              <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
              <serviceThrottling maxConcurrentCalls="10000" maxConcurrentSessions="10000">    
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
              <serviceCredentials>
                <userNameAuthentication 
                  userNamePasswordValidationMode="Custom" 
                  customUserNamePasswordValidatorType="MYAPPHost.Authenticate, MYAPPHost"/>
              </serviceCredentials>         
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="OverAllEndPointBehavior" />
          </endpointBehaviors>
        </behaviors>        
        <bindings>
          <netTcpBinding>
            <binding name="ServiceTCPEndPointBinding" maxBufferSize="2147483647">    
              <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
    maxNameTableCharCount="2147483647" />
              <security mode="TransportWithMessageCredential">
                <transport clientCredentialType="None" />
                <message clientCredentialType="UserName" algorithmSuite="TripleDes"/>
              </security>
            </binding>
          </netTcpBinding>
        </bindings>        
        <services>
          <service behaviorConfiguration="OverAllServiceBehavior"
                   name="MiddleWare.ServiceClasses.ServiceClass">    
            <host>
              <baseAddresses>
                <add baseAddress="net.tcp://127.0.0.1:15010/ServiceTCPEndPointMEX"/>            
              </baseAddresses>
            </host>    
            <endpoint address="net.tcp://127.0.0.1:15020/ServiceTCPEndPoint" contract="MiddleWare.ServiceContracts.IServiceContract" />           
            <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />    
          </service>
        </services>
      </system.serviceModel>
    </configuration>
    

    验证类:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IdentityModel.Selectors;
    
    namespace MYAPPHost
    {
        public class Authenticate : UserNamePasswordValidator
        {
            public override void Validate(string UserName, string Password)
            {
                if (!CheckFromDB(UserName,Password))
                    throw new Exception("UNAUTHORIZED ACCESS!!!");
            }
        }
    }
    

    在客户端,添加对WCF(SR)的引用

    之后
    SR.ServiceContractClient obj = new SR.ServiceContractClient("ServiceTCPEndPoint");
    obj.ClientCredentials.UserName.UserName = "User1";
    obj.ClientCredentials.UserName.Password = "Password1";
    int I = obj.Add(1, 2);
    

    如果未提供凭据,则抛出消息安全性令牌错误。如果出现错误的凭据UNAUTHORIZED ACCESS