Подтвердить что ты не робот

Аутентификация веб-API ASP.NET MVC 4 с помощью поставщика членства

У меня есть проект ASP.NET MVC 4 с использованием веб-API. На контроллере я установил для класса требование авторизации с использованием атрибута [Авторизовать]. Для проверки подлинности я использую провайдер членства ASP.NET и установил, что мой Web.Config использует аутентификацию "Forms". Вот где я застрял:

Все работает отлично до тех пор, пока я не закончил тестирование API, и я хочу защитить контроллер с помощью атрибута [Authorize], чтобы я мог начать тестировать проверку подлинности в отношении пользователей моего провайдера членства. Поэтому я запускаю Fiddler и делаю тот же вызов, добавляя атрибут Authorization: Basic вместе с именем пользователя: password из моего поставщика членства следующим образом:

enter image description here

Ответ, который я получаю, несанкционирован 401, и в разделе "Auth" я получаю "Нет заголовка WWW-Authenticate". Тогда я понимаю, что API ищет кодированный SHA1 ключ. Поэтому я запускаю генератор SHA1 из поиска и получаю хэш для моего имени пользователя: пароль и обновляю свой заголовок запроса следующим образом:

enter image description here

Это тоже не работает, и я получаю те же результаты. Кроме того, мне явно нужен какой-то "общий секретный ключ" для использования с сервером для декодирования моего имени пользователя/пароля.

Итак, мои вопросы:

  • Как получить этот ключ с сервера (или в этом случае Virtual IIS запущен VS 2012).
  • Как это сделать, чтобы делать аутентифицированные вызовы в Fiddler, используя имена пользователей/пароли от поставщика членства ASP.NET.
  • Как я буду использовать это в своем клиентском приложении для выполнения тех же вызовов (С# WPF App).
  • Является ли это лучше всего в сочетании с SSL на моих HTTP-вызовах? Если нет, то что?

Спасибо заранее!

4b9b3361

Ответ 1

Вы можете использовать базовую аутентификацию с помощью SSL. На стороне сервера мы могли бы написать пользовательский обработчик делегирования, который будет проверять учетные данные, запросив зарегистрированный поставщик memebership, и, если он действителен, получить роли и установить текущего принципала:

public class BasicAuthenticationMessageHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var authHeader = request.Headers.Authorization;

        if (authHeader == null)
        {
            return base.SendAsync(request, cancellationToken);
        }

        if (authHeader.Scheme != "Basic")
        {
            return base.SendAsync(request, cancellationToken);
        }

        var encodedUserPass = authHeader.Parameter.Trim();
        var userPass = Encoding.ASCII.GetString(Convert.FromBase64String(encodedUserPass));
        var parts = userPass.Split(":".ToCharArray());
        var username = parts[0];
        var password = parts[1];

        if (!Membership.ValidateUser(username, password))
        {
            return base.SendAsync(request, cancellationToken);
        }

        var identity = new GenericIdentity(username, "Basic");
        string[] roles = Roles.Provider.GetRolesForUser(username);
        var principal = new GenericPrincipal(identity, roles);
        Thread.CurrentPrincipal = principal;
        if (HttpContext.Current != null)
        {
            HttpContext.Current.User = principal;
        }

        return base.SendAsync(request, cancellationToken);
    }
}

Затем мы регистрируем этот обработчик в Application_Start:

GlobalConfiguration.Configuration.MessageHandlers.Add(
    new BasicAuthenticationMessageHandler()
);

Теперь у нас может быть контроллер Api, который будет украшен атрибутом [Authorize], чтобы гарантировать, что только проверенные подлинности пользователи могут получить доступ к своим действиям:

[Authorize]
public class ValuesController : ApiController
{
    public string Get()
    {
        return string.Format("Hello {0}", User.Identity.Name);
    }
}

Хорошо, теперь посмотрим на пример клиента:

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

class Program
{
    static void Main()
    {
        // since for testing purposes I am using IIS Express
        // with an invalid SSL certificate I need to desactivate
        // the check for this certificate.
        ServicePointManager.ServerCertificateValidationCallback += 
            (sender, certificate, chain, sslPolicyErrors) => true;

        using (var client = new HttpClient())
        {
            var buffer = Encoding.ASCII.GetBytes("john:secret");
            var authHeader = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(buffer));
            client.DefaultRequestHeaders.Authorization = authHeader;
            var task = client.GetAsync("https://localhost:44300/api/values");
            if (task.Result.StatusCode == HttpStatusCode.Unauthorized)
            {
                Console.WriteLine("wrong credentials");
            }
            else
            {
                task.Result.EnsureSuccessStatusCode();
                Console.WriteLine(task.Result.Content.ReadAsAsync<string>().Result);
            }
        }
    }
}