Аутентифікація за логіном-паролем та сертифікатом у WCF при використанні Message Security

У цій статті описано як створити WCF-сервіс, який реалізує два види аутентифікації клієнтів: за логіном-паролем та сертифікатом при використанніMessage Security. Причому обидва види реалізують власну логіку автентифікації.

В даному прикладі як сервісний сертифікат використовується сертифікат ГОСТ, хоча приблизно аналогічні настройки будуть застосовуватись з будь-якими типами сертифікатів. Для коректної роботи ГОСТ-сертифікатів необхідно встановити пакетиCryptoPro CSP таКріптоПРО.NET.

1. Аутентифікація за логіном-паролем

Процес умовно можна поділити на 3 етапи:

  • створення та налаштування сервісу;
  • створення класу, що реалізує власну логіку автентифікації;
  • створення програми-клієнта.

Створення та налаштування сервісу

Створіть у Visual Studio проект WCF-сервісу. Для цього прикладу я використовував тип проектуWCF Service Application. У цьому Visual Studio автоматично створить сервісService1.svc з тестовими методами. Його ми і будемо використовувати як приклад.

Далі потрібно настроїти конфігурацію сервісу. Це можна зробити вручну або за допомогою утилітиWCF Service Configuration Editor, яка вбудована у Visual Studio і дозволяє настроювати сервіс у графічному режимі. Для цього клацніть правою кнопкою миші на файліWeb.config і виберітьEdit WCF Configuration. Відкриється вікно налаштування параметрів сервісу, як показано на рис. 1. Якщо у вас немає цього пункту, перейдіть на вкладкуTools і натиснітьWCF Service Configuration Editor. Після цього пункт меню має з'явитися.

логіном-паролем

Мал. 1. Вікно налаштування параметрів WCF-сервісу

Спочатку створимо прив'язку для сервісу, що підтримує аутентифікацію за логіном-паролем. Для цього клацніть на вузолBindings у лівій частині вікна, а потім за посиланнямNew Binding Configuration… у правій частині. У списку виберіть тип прив'язкиwsHttpBinding і натиснітьOK. У поліName введіть назву прив'язки, наприклад,UserNameBinding. Інші налаштування можна залишити за замовчуванням, докладніше вони описані тут. Далі перейдіть на вкладкуSecurity і налаштуйте параметри таким чином:

  • Mode - Message;
  • MessageClientCredentialType - UserName;
  • TransportClientCredentialType - None.

Також, якщо використовується сертифікат з алгоритмом ГОСТ, то необхідно виставити параметрNegotiateServiceCredential уFalse. Цей параметр вказує, чи буде інформація про сертифікат сервісу автоматично передаватися на клієнт або в клієнті необхідно вручну вказувати сертифікат сервісу. З ГОСТ-сертифікатами це не працює, тому виставляємо параметрFalse. Інші параметри залиште за замовчуванням.

Далі створимо для сервісу поведінку (Behavior ). Для цього розгорніть вузолAdvanced, даліService Behaviors і в правій частині вікна натиснітьNew Service Behavior Configuration. У поліName введіть назву, наприкладAuthenticationBehavior. Далі за допомогою кнопкиAdd… додайте елементи як описано нижче.

  • ServiceMetadata. Виставте параметрHttpGetEnabled уTrue, щобwsdl був доступний на сторінці сервісу.
  • ServiceDebug. Виставте параметрIncludeExceptionDetailsInFaults уTrue. Це зручно для цілейналагодження, тому що всі винятки сервісу будуть прокидатися на клієнт. При розгортанні на продуктивному сервері це налаштування краще відключати і прокидати на клієнт лише ті винятки, які вважаєте за потрібне.
  • ServiceCredentials. Оскільки використовуватиметься власна логіка аутентифікації, то параметрUserNamePasswordVal >
    message

Мал. 2. Налаштування сертифіката сервісу

Клацніть на сервісі та у правій частині вікна у параметріBehaviorConfiguration виберіть створену раніше поведінкуAuthenticationBehavior. Далі розкрийте вузолEndpoints сервісу, клацніть по створеномуEndpoint і призначте ім'я, наприклад,UserNameEndpoint. Інші параметри залиште за замовчуванням.

На цьому конфігурація сервісу закінчена, натиснітьCTRL+S для збереження та закрийте вікно. ФайлWeb.config буде змінено відповідно.

Створення класу, що реалізує власну логіку аутентифікації

Далі необхідно створити клас, який був вказаний при налаштуванні та який реалізовуватиме логіку автентифікації користувачів. В даному випадку це клас, який повинен знаходитися в тій же збірці у просторі іменServiceWithAuthentication і мати назвуCustomUserNameValidator. Для того, щоб цей клас міг здійснювати валідацію, його необхідно успадкувати від класуUserNamePasswordValidator, який знаходиться у збірціSystem.IdentityModel, та перевизначити методValidate. В даному прикладі метод просто перевірятиме одного конкретного користувача і відкидатиме всіх інших. Нижче наведено код:

Щоб перевірити конфігурацію сервісу, клацніть правою кнопкою миші на файліService1.svc і натиснітьView in Browser. При цьому, якщо всебуло зроблено правильно, має відкритися сторінка сервісу, як показано на рис. 3.

використанні

Мал. 3. Сторінка сервісу

Створення програми-клієнта

Далі відкрийте файлProgram.cs і відредагуйте його так:

Запустивши цей код, ви повинні побачити в консолі рядок "You entered: 25". Це означає, що сервіс та автентифікація відпрацювали правильно. Спробуйте змінити логін або пароль і ви отримаєтеMessageSecurityException, що означатиме, що користувач не пройшов аутентифікацію.

2. Аутентифікація за сертифікатом

Тепер розглянемо автентифікацію за сертифікатом. Для цього додамо до сервісу ще одну кінцеву точку.

Клацніть правою кнопкою миші на файліWeb.config сервісу та виберіть пункт менюEdit WCF Configuration. Для початку необхідно трохи змінити створену раніше поведінку. Перейдіть доAuthentiactionBehavior (Advanced —> Service Behaviors —> AuthentiactionBehavior ), розкрийте його вузолserviceCredentials і далі вузолclientCredentials. Для власної логіки перевірки сертифіката клієнта виставте властивістьCertificateValidationMode уCustom, а в поліCustomCertificateValidatorType введіть повне найменування класу (включаючи складання), який перевірятиме сертифікат. У цьому прикладі це будеServiceWithAuthentication.CustomCertificateValidator, ServiceWithAuthentication.

Далі розкрийте вузолBindings і в правій частині вікна натисніть на посиланняNew Binding Configuration…. У спливаючому вікні виберітьwsHttpBinding та натиснітьОК. Буде створено нову прив'язку. У поліName вкажіть найменування, наприклад,CertificateBinding та на вкладціSecurity виставте параметринаступним чином:

  • Mode - Message;
  • MessageClientCredentialType - Certificate;
  • NegotiateServiceCredential - False
  • TransportClientCredentialType - None.

Далі перейдіть до вузлаServices, розкрийте створений раніше сервіс, клацніть правою кнопкою миші по вузлуEndpoints і натиснітьNew Service Endpoint. Заповніть поля наступним чином:

  • Name - CertificateEndpoint;
  • Address - ByCertificate;
  • Binding - wsHttpBinding;
  • BindingConfiguration-CertificateBinding;
  • Contract - ServiceWithAuthentication.IService1.

Збережіть зміни та закрийте вікно.

Далі необхідно створити сам клас, який перевірятиме клієнтський сертифікат. В даному випадку це будеCustomCertificateValidator. Клас необхідно успадкувати відX509CertificateValidator і перевизначити методValidate. Для прикладу прийматимемо лише сертифікат з певним відбитком і відсіватимемо всі інші. Код буде приблизно такий:

Клацніть правою кнопкою файлуService1.svc і натиснітьView in Browser. Якщо все зроблено правильно, то, як і раніше, має відкритися сторінка сервісу.

Тепер перейдіть до клієнта, клацніть правою кнопкою миші по сервісу та натиснітьUpdate Service Reference, щоб оновити посилання на сервіс.

Далі відкрийте файлProgram.cs і відредагуйте його наступним чином (змініть параметри пошуку сертифіката на свої):

Запустіть клієнта. Якщо все зроблено правильно, ви побачите у консолі два рядки. При цьому в першому випадку відпрацювала автентифікація за логіном-паролем, а в другому за сертифікатом.

3. Додаткові налаштування

Вказівка ​​сертифікатасервісу на клієнті

За умовчанням, коли ви додаєте посилання на сервіс через менюAdd Service Reference…, у файлApp.config клієнта додається сертифікат сервісу в кодованому вигляді як показано нижче:

Не завжди зручно, наприклад, при зміні сертифіката сервісу. Є інший спосіб вказівки сертифіката сервісу клієнта. Відкрийте файлApp.config клієнта, видаліть елемент , а замість нього додайте елемент із параметрами для пошуку сертифіката сервісу (сертифікат сервісу з відкритим ключем має бути встановлений у сховищі). ФайлApp.config після цього має виглядати приблизно так:

Спробуйте тепер знову запустити клієнтський додаток, якщо параметри пошуку сертифіката задані правильно, все має спрацювати як і раніше.