Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> WCF Basic аутентификация, Реализация Basic аутентификации в WCF 
:(
    Опции темы
tikskit
Дата 19.1.2016, 08:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 17.5.2008

Репутация: нет
Всего: нет



Привет! Я делаю basic-авторизацию в WCF. 

Я в этом новичок и мои попытки основаны на серии статей http://leastprivilege.com/2008/01/11/http-...t-part-0-intro/ 
Я использую привязку webHttpBinding и HTTPS включен

Главная идея - реализовать интерфейс IHttpModule следующим образом
  • Когда пользователь отправляет запрос, модуль проверяет присутствует ли в запросе заголовок Authorization
  • Если Authorization присутствует, модуль извлекает его значение, декодирует логин и пароль из Base64 и проверяет совпадение
  • Если Authorization отсутствует, модуль возвращает код 401 с заголовком WWW-Authenticate

Вот моя реализация модуля:

Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Management;
using System.Text;

namespace MyProj_A
{
    public class MyHTTPModule : IHttpModule
    {

        void IHttpModule.Dispose()
        {
        }

        void IHttpModule.Init(HttpApplication context)
        {
            context.BeginRequest += Context_BeginRequest;
            context.AuthenticateRequest += OnEnter;
            context.EndRequest += OnLeave;
        }


        private void Context_BeginRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            context.Response.Write("BeginRequest");
        }

        void OnEnter(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            if (IsHeaderPresent())
            {
                if (!AuthenticateUser())
                {
                    DenyAccess();
                }
            }
            else
            {
                // if anonymous requests are not allowed - end the request
                DenyAccess();
            }
        }

        bool IsHeaderPresent()
        {
            return HttpContext.Current.Request.Headers["Authorization"] != null;
        }

        bool AuthenticateUser()
        {
            string username = "", password = "";
            string authHeader = HttpContext.Current.Request.Headers["Authorization"];
            if (authHeader != null && authHeader.StartsWith("Basic"))
            {
                // extract credentials from header
                string[] credentials = ExtractCredentials(authHeader);
                username = credentials[0];
                password = credentials[1];
                if (username.CompareTo("tikskit") == 0 && password.CompareTo("") == 0)
                {
                    return true;
                } else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }


        private static void DenyAccess()
        {
            HttpContext context = HttpContext.Current;

            context.Response.StatusCode = 401;
            context.Response.End();
        }

        void OnLeave(object sender, EventArgs e)
        {
            // check if module is enabled
            if (HttpContext.Current.Response.StatusCode == 401)
            {
                SendAuthenticationHeader();
            }
        }

        private void SendAuthenticationHeader()
        {
            HttpContext context = HttpContext.Current;

            context.Response.StatusCode = 401;
            context.Response.AddHeader(
                "WWW-Authenticate",
                "Basic realm=\"yo-ho-ho\""
                );

        }
    }

}


И вот мой web.config

Код

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2"/>
    <customErrors mode="Off" />
  </system.web>


  <system.serviceModel>
    <behaviors>

      <endpointBehaviors>
        <behavior name="webBehavior">
          <webHttp automaticFormatSelectionEnabled="false"/>
        </behavior>
      </endpointBehaviors>

       <serviceBehaviors>
        <behavior name="Default" >
          <serviceMetadata httpGetEnabled="false" />
          <serviceMetadata httpsGetEnabled="false"/>
          <serviceAuthenticationManager authenticationSchemes="Basic"/>
          <serviceCredentials>
          </serviceCredentials>

        </behavior>
      </serviceBehaviors>

    </behaviors>

    <bindings>      
      <webHttpBinding>
        <binding name="MyBinding">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Basic"/>
          </security>
        </binding>
      </webHttpBinding>
    </bindings>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

    <services>
      <service name="MyProj_A.Service1">
        <endpoint address="" binding="webHttpBinding" contract="MyProj_A.IService1"
                  behaviorConfiguration="webBehavior"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <diagnostics>
      <endToEndTracing activityTracing="false" messageFlowTracing="true" propagateActivity="true"></endToEndTracing>
    </diagnostics>
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="MyHTTPModule"
        type="MyProj_A.MyHTTPModule,MyProj-A"/>
    </modules>

    <directoryBrowse enabled="false"/>
  </system.webServer>

</configuration>


Я компилирую и публикую проект под IIS 7.5 на удаленном компьютере и подключаюсь к нему из Visual Studio через remote debugger, предварительно расставив брейкпойнты в Context_BeginRequest, OnEnter и OnLeave.

Потом я отправляю запрос к моей WCF из браузера, используя URL. И вот что происходит:
  • После того, как я жму в браузере Enter, срабатывает Context_BeginRequest
  • Там я могу видеть из VS, что заголовок Authorization в запросе отсутствует
  • Срабатывает OnEnter, где в конце концов ответу присваивается код 401
  • Срабатывает OnLeave, где в ответ добавляется заголовок WWW-Authenticate
  • В браузере отображается стандартное окно запроса пароля и логина
  • Ввожу в этом окне логин и пароль и жму ОК
  • Срабатывает Context_BeginRequest, где я вижу, что заголовок Authorization присутствует с значением "Basic <логин и пароль в Base64>"
  • На этот раз OnEnter не срабатывает
  • Выполнение попадает в OnLeave, где значение HttpContext.Current.Response.StatusCode уже почему-то равно 401

У меня следующие вопросы:
  • Почему OnEnter не срабатывает во второй раз, когда браузер присылает запрос с Authorization в заголовках? Вот тут сказано, что AuthenticateRequest срабатывает тогда, когда пользователь уже прошел аутентификацию. Тогда я не понимаю, почему OnEnter срабатывает в первый раз, когда никто еще не вводил никакого пароля? У меня каким-то образом включена анонимная аутентификация? Я в IIS удалил все модули аутентификации, кроме BasicAuthenticationModule! Манипуляции с <authentication mode="Forms"/> в <system.web> тоже ничего не дали
  • Почему, когда браузер присылает запрос с Authorization, в OnLeave код ответа уже установлен 401? Что и где это устанавливает?
  • Как мне правильно настроить мой web.config и IIS и как правильно реализовать Basic-аутентификацию?

Спасибо!
PM MAIL WWW   Вверх
tikskit
Дата 21.1.2016, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 17.5.2008

Репутация: нет
Всего: нет



Вопрос закрыт

Забыл сослаться на конфигурацию binding в конфигурировании endpoint
Код

<endpoint address="" binding="webHttpBinding" contract="MyProj_A.IService1"
                  behaviorConfiguration="webBehavior"
                  bindingConfiguration="MyBinding"/>

PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Любитель
Mymik
mr.DUDA

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Любитель, Mymik, mr.DUDA.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Разработка под ASP.NET | Следующая тема »


 




[ Время генерации скрипта: 0.0978 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.