Пользовательская безопасность WCF через netTcp - PullRequest
3 голосов
/ 27 ноября 2011

Я новичок в WCF, и я делаю серверное / клиентское приложение, в котором мне нужно иметь некоторую схему пользователя / пароля, чтобы поддерживать некоторые параметры настройки для каждого клиента и регистрировать, кто обращается к службе, но "безопасность" втрафик, проходящий через сеть, в действительности не нужен, поскольку информация не является конфиденциальнойПоэтому, принимая это во внимание, я искал ПРОСТОЙ способ сделать это, но я не смог его найти.

У меня есть несколько ограничений и условий:

  • Безопасность Windows не вариант.
  • Я использую развертывание clickonce, поэтому все должно содержаться вустановочный пакет.Я не знаю фактического списка пользователей, которые его скачивают, поэтому у меня нет способа разослать какой-либо сертификат всем пользователям.
  • Также клиент будет принят в локальной сети и через несколько глобальных сетей.,Другое требование, которое должно быть выполнено, заключается в том, что служба должна иметь очень хорошую производительность, поскольку большое количество данных передается с каждым ответом, поэтому возникают следующие вопросы:

Плохо ли влияет на безопасность сообщений производительность?

"Ручным" способом было бы передать имя пользователя в качестве параметра для каждого метода, который я раскрываю, но это выглядит как очень грязное решение.

Мне кажется, есть много ограничений для разработки этого, поэтому я спрашиваю об этом.

Какое было бы самое простое решение для достижения этой цели?

1 Ответ

2 голосов
/ 19 января 2012

Прежде всего, мы должны предположить, что все пользователи, использующие сервис, каким-то образом «зарегистрированы» для использования сервиса.Потому что, если оно открыто, анонимно, то отслеживания просто нет.Поэтому я предполагаю следующее:

  1. Служба размещена в Windows Service / WinForms для поддержки TCP Endpoint.- В новых версиях IIS (> 6) это больше не является обязательным предположением
  2. Существует такая комбинация, как «Имя пользователя / Пароль» для аутентификации.Это не в активном каталоге (без проверки подлинности Windows), но может быть xml / database.
  3. Мы не хотим иметь методы, такие как public int Add(string User, string Password, int A, int B)

У меня есть службас конечной точкой TCP, которая делает что-то вроде этого.Я поделюсь этим.Я не утверждаю, что это лучшая практика.

Имя приложения MYAPP

Я предоставил

customUserNamePasswordValidatorType="MYAPPHost.Authenticate, MYAPPHost" 

в

serviceCredentials > userNameAuthentication 

разделе.of web.config.

MYAPPHost - это имя моей службы Windows.Authenticate - это класс, который выполняет аутентификацию из базы данных.

message clientCredentialType="UserName" установлен для TCPBinding.

App.Config моей службы Windows:

<?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 происходит.

...