WCF .net 4.0 HTTP базовая аутентификация

#c# #asp.net #wcf #rest #restful-authentication

#c# #asp.net #wcf #остальное #restful-аутентификация

Вопрос:

Я искал это уже пару дней.

Я просто пытаюсь передать имя пользователя / пароль в мою службу RESTful, используя базовые проверки подлинности HTTP. Все остальное работает потрясающе!

Вот как выглядит мой web.config:

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

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
  </system.webServer>

  <system.serviceModel>

    <bindings>
      <wsHttpBinding>
        <binding name="">
          <security mode="Message">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

    <standardEndpoints>
      <webHttpEndpoint>
        <!-- 
            Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
            via the attributes on the <standardEndpoint> element below
        -->
        <standardEndpoint name="" helpEnabled="true" defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ParkingPandaREST.CustomUserNameValidator, ParkingPandaREST" />
          </serviceCredentials>      
        </behavior>
      </serviceBehaviors>
    </behaviors>


  </system.serviceModel>

</configuration>
  

Затем я создал класс CustomUserNameValidator, который имеет следующее:

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

namespace ParkingPandaREST
{
    public class CustomUserNameValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
    {
        // This method validates users. It allows in two users, test1 and test2 
        // with passwords 1tset and 2tset respectively.
        // This code is for illustration purposes only and 
        // must not be used in a production environment because it is not secure.    
        public override void Validate(string userName, string password)
        {
            if (null == userName || null == password)
            {
                throw new ArgumentNullException();
            }

            if (!(userName == "test1" amp;amp; password == "1tset") amp;amp; !(userName == "test2" amp;amp; password == "2tset"))
            {
                // This throws an informative fault to the client.
                throw new System.ServiceModel.FaultException("Unknown Username or Incorrect Password");
                // When you do not want to throw an infomative fault to the client,
                // throw the following exception.
                // throw new SecurityTokenException("Unknown Username or Incorrect Password");
            }
        }
    }
}
  

Я просто запускаю службу на своем локальном компьютере и пытаюсь достичь точки останова в классе CustomUserNameValidator, но она никогда не попадает туда. Итак, я не использую SSL прямо сейчас, просто пытаюсь получить передаваемое имя пользователя / пароль.

Ответ №1:

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

Примечание: Отключите базовую аутентификацию в IIS

            // Get the Header Authorization Value
            string headerValue = operationContext.IncomingRequest.Headers[HttpRequestHeader.Authorization];
            headerValue = headerValue.Replace("Basic ", "");
            headerValue = DecodeBase64String(headerValue);

            // Get Username and Password
            string userName = headerValue.Substring(0, headerValue.IndexOf(":"));
            string password = headerValue.Substring(headerValue.IndexOf(":")   1, headerValue.Length - userName.Length - 1);

            // Do Custom Authorization here with the userName and password
  

…….

Также здесь находится функция DecodeBase64String

     public static string DecodeBase64String(string encodedData)
    {
        byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
        string returnValue = System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
        return returnValue;
    }
  

Надеюсь, это поможет некоторым другим людям, у которых была такая же проблема — ура!

Комментарии:

1. Я бы рекомендовал использовать Encoding.UTF8.getString(encodedData), хотя

Ответ №2:

Привязкой по умолчанию для HTTP-транспорта в WCF 4 является BasicHttpBinding. Если вы преобразуете свой элемент wsHttpBinding в элемент BasicHttpBinding и настраиваете его для пользовательской проверки, тогда ваш код должен выполняться.

Комментарии:

1. Я только что попытался изменить <wsHttpBinding> на <BasicHttpBinding> и все еще не смог добиться, чтобы он достиг точки останова. Я что-то еще упускаю?

2. Возможно, конфигурация вашего клиента и конфигурация службы не синхронизированы. Кроме того, вам необходимо настроить IIS, чтобы разрешить базовую аутентификацию HTTP. Конфигурация IIS будет отличаться в зависимости от версии, но вот конфигурация IIS 7: technet.microsoft.com/en-us/library/cc772009 (WS.10).aspx

3. Итак, это не будет работать на моем локальном компьютере разработчика с использованием VS2010 — просто нажмите F5 и переведите его в режим отладки?

4. Я не пытался сделать это с помощью встроенного веб-сервера разработки Visual Studio. Если проект службы является приложением-службой WCF, то вы должны иметь возможность перейти на вкладки свойств проекта, а на вкладке Web есть возможность использовать локальный сервер IIS. VS автоматически создаст веб-сайт для службы. После ее настройки настройте локальный IIS для базовой аутентификации HTTP. Затем F5 будет работать в этом режиме в обычном режиме. По крайней мере, это то, что я делал в прошлом 🙂

5. И вы смогли использовать пользовательскую базовую аутентификацию HTTP? У меня не было этой проблемы: samuelotter.com/blog/2010/07 /…

Ответ №3:

Базовая аутентификация — это протокол HTTP. Таким образом, это безопасность транспорта, а не безопасность сообщений. Ваша конфигурация должна содержать этот фрагмент:

 <security mode="Transport">
    <transport clientCredentialType="Basic" />
</security>
  

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

Комментарии:

1. Для обработки базовой аутентификации для моих сервисов я использую: altairiswebsecurity.codeplex.com Я размещаю свои сервисы как контроллер MVC вместо WCF.

2. Итак, с новой версией WCF вы не можете выполнять базовую аутентификацию HTTP должным образом… вау, это ужасно!

3. @Codo Не могу перейти по вашей ссылке в блог: (у меня такая же проблема с тем, что мой пользовательский валидатор не выполняется