Ограничить функциональность веб-службы WCF на основе группы пользователей - PullRequest
4 голосов
/ 27 августа 2009

У меня есть веб-служба WCF, которая использует клиентское приложение C #. У меня также есть 4 группы, хранящиеся в Active Directory. Клиентское приложение передает учетные данные пользователя для подключения этого веб-сервиса.

Веб-сервис, предоставляющий клиентскому приложению доступ к нескольким API или методам, следующим образом:

    [OperationContract]
    bool Read();


    [OperationContract]
    bool Write();

Метод Read () должен быть доступен для всех клиентов

Метод Write () должен быть доступен только пользователям, принадлежащим к определенной группе пользователей Windows, поддерживаемой Active Directory.

Вопрос: Как мы можем отфильтровать или ограничить открытый интерфейс или метод по клиенту на основе его группы пользователей, поддерживаемой в AD?


jrista, Спасибо за ваш ответ. Я попробовал те же директивы, что и PrincipalPermission, следующим образом:

[PrincipalPermission(SecurityAction.Demand, Role = "Readers")]
[OperationContract]
bool Read();

[PrincipalPermission(SecurityAction.Demand, Role = "Writers")]
[OperationContract]
bool Write();

Но это не работает. Пользователь группы чтения также может вызывать метод Writer (), а пользователь группы чтения также может вызывать метод Write ().

Я хочу сказать вам одну вещь: я использую BasicHttpBind в моем файле web.config следующим образом:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBind">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" proxyCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="DXDirectory.DXDirectoryService" behaviorConfiguration="DXDirectory.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBind"
                  name="BasicBinding" contract="DXDirectory.IDXDirectoryService">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DXDirectory.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceAuthorization principalPermissionMode="UseWindowsGroups"/>          
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Требуется ли реализовать wsHttpBinding для этой функции? Если да, то как я могу реализовать wsHttpBinding в моем веб-сервисе?

Ответы [ 4 ]

4 голосов
/ 27 августа 2009

jrista прав - вы можете использовать встроенные службы авторизации Windows, включая атрибут «PrincipalPermission», чтобы ограничить доступ.

НО: прежде чем вы сможете авторизоваться, вам необходимо пройти аутентификацию. Прежде всего вам необходимо знать, кто стучится в дверь вашей службы, прежде чем решить, впустить его (или ее) или нет.

Для этого необходимо использовать учетные данные Windows при обмене сообщениями, а клиент и сервер должны находиться в одном домене (или в доменах с отношениями взаимного доверия). Кроме того, вам необходимо использовать привязку, например wsHttp или netTcp, которая по умолчанию разрешает и поддерживает учетные данные Windows, и вам необходимо убедиться, что вы используете и настраиваете конфигурацию безопасности привязки, которая передает учетные данные Windows от клиента к серверу.

Вам понадобится что-то вроде:

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="Secured">
        <security mode="Transport">
          <transport clientCredentialType="Windows" />
        </security>
      </binding>
    </netTcpBinding>
  </bindings>
</system.serviceModel>

и затем вам нужно будет сослаться на эту конфигурацию привязки от конечных точек вашего клиента и сервера.

WsHttpBinding и NetTcpBinding по умолчанию используют учетные данные клиента Windows, поэтому из коробки, если вы полностью не отключили защиту, вы должны получить поддержку учетных данных Windows в этих двух привязках.

Марк

PS:
Как показывает jrista (как я уже делал в предыдущем ответе на почти такой же вопрос , что у вас был), вам действительно нужно только добавить этот атрибут PrincipalPermission в методы, которые вы хотите ограничить для пользователей, принадлежащих к определенной группе. - не нужно вручную возиться с членством в группе AD и т. д.

Если вы действительно должны получить группы, к которым принадлежит пользователь, вызывающий вашу службу, вы можете проверить свойство ".Groups" WindowsIdentity, которое вызывает:

WindowsIdentity winCaller = ServiceSecurityContext.Current.WindowsIdentity;
foreach(var group in winCaller.Groups)
{
   Console.WriteLine(group.Value);
}

Если вам нужно имя пользователя, который звонит, используйте winCaller.Name. Если вам нужен SID для вызова пользователя, используйте winCaller.User. Там все в порядке - без проблем, без сложного кода - просто используйте его! : -)

4 голосов
/ 27 августа 2009

Я не совсем уверен, как интегрировать учетные данные AD в обычную среду безопасности .NET. Однако это возможно (я посмотрю, смогу ли я найти некоторые ссылки), и как только вы это сделаете, вы сможете использовать стандартный атрибут безопасности для проверки «роли», которая будет соответствовать вашей группе AD:

[OperationContract]
bool Read();

[PrincipalPermission(SecurityAction.Demand, Role = "Writers")]
[OperationContract]
bool Write();

Чтобы использовать группы AD, настройте поведение службы:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <adServiceBehavior>
        <serviceAuthorization principalPermissionMode="UseWindowsGroups" />
      </adServiceBehavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Была еще одна мысль. Иногда возникает желание вообще не иметь метода Write () на интерфейсе. С помощью WCF вы можете реализовать несколько интерфейсов контрактов на обслуживание в одном классе обслуживания. Идеальным решением может быть создание двух интерфейсов контрактов на обслуживание, один с Read () и Write (), один с просто Read (). В зависимости от пользователя, вошедшего в клиент, вы можете использовать интерфейс Read () для тех, кто имеет только права на чтение, и интерфейс Read () / Write () для тех, кто имеет доступ к обоим. Это также позволит вам предоставить самый безопасный контракт на обслуживание клиентам, которые не должны иметь права на запись, при этом используя контракт на чтение / запись для внутренних целей в административных целях. Вы никогда не подвергаете код, который потенциально может быть использован таким образом.

0 голосов
/ 01 августа 2012

Попробуйте добавить атрибут Principalpermission для метода в классе обслуживания, а не в контракте операции в интерфейсе службы.

0 голосов
/ 28 августа 2009

Если вы пользуетесь хостингом в IIS, настроен ли сервер на анонимность?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...