Как использовать OpenID в УСПОКОИТЕЛЬНОМ API?

Я думаю, что это большая часть устойчивой версии для C#:

using System;
using System.Collections;
using System.Threading;

namespace DoFactory.GangOfFour.Singleton.RealWorld
{

  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Same instance?
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 server requests
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // "Singleton"

  class LoadBalancer
  {
    private static LoadBalancer instance;
    private ArrayList servers = new ArrayList();

    private Random random = new Random();

    // Lock synchronization object
    private static object syncLock = new object();

    // Constructor (protected)
    protected LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      // Support multithreaded applications through
      // 'Double checked locking' pattern which (once
      // the instance exists) avoids locking each
      // time the method is invoked
      if (instance == null)
      {
        lock (syncLock)
        {
          if (instance == null)
          {
            instance = new LoadBalancer();
          }
        }
      }

      return instance;
    }

    // Simple, but effective random load balancer

    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

Вот оптимизированная.NET версия :

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Singleton.NETOptimized
{

  // MainApp test application

  class MainApp
  {

    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Confirm these are the same instance
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 requests for a server
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // Singleton

  sealed class LoadBalancer
  {
    // Static members are lazily initialized.
    // .NET guarantees thread safety for static initialization
    private static readonly LoadBalancer instance =
      new LoadBalancer();

    private ArrayList servers = new ArrayList();
    private Random random = new Random();

    // Note: constructor is private.
    private LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      return instance;
    }

    // Simple, but effective load balancer
    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

можно найти этот шаблон в dotfactory.com .

31
задан Pēteris Caune 2 December 2009 в 14:20
поделиться

3 ответа

Сейчас я потратил некоторое время на изучение вариантов и хотел бы подвести итоги. Во-первых, немного больше контекста - я разрабатываю и контролирую как сервис, так и потребителя API. Consumer - это приложение на основе Flash, которое обслуживается с того же хоста, что и API, и предполагается, что оно будет использоваться в браузере. Сторонних клиентов пока нет.

Таким образом, вопрос можно разделить на две части:

  • как мне выполнить аутентификацию OpenID через API
  • как мне поддерживать «аутентифицированное» состояние в последующих запросах

Для первой части аутентификация OpenID почти всегда включает интерактивные шаги. Во время процесса аутентификации, скорее всего, будет этап, на котором пользователь находится на веб-странице провайдера OpenID, входит в систему и нажимает какую-то кнопку «Я согласен». Таким образом, API не может и не должен обрабатывать это прозрачно (не «скажите мне своего провайдера OpenID и пароль, а я сделаю все остальное»). Лучшее, что он может сделать, - это передавать HTTP-ссылки вперед и назад, которые клиент должен открывать и выполнять инструкции.

Поддержание «аутентифицированного» состояния

API-интерфейсы REST должны быть без сохранения состояния, каждый запрос должен включать всю информацию, необходимую для его обработки, верно? Нет смысла проходить аутентификацию с помощью провайдера OpenID для каждого запроса, поэтому какой-то сеанс необходим. Некоторые из вариантов передачи сеансового ключа (или «токена доступа» или имени пользователя / пароля):

  • HTTPS + BASIC-аутентификация (заголовок «Авторизация: базовая ...» в каждом запросе)
  • Запросы на подпись В стиле Amazon (заголовок «Авторизация: AWS ...» в каждом запросе)
  • OAuth: получить токен доступа, включать этот и множество других параметров в каждый запрос
  • Cookie, в котором хранится ключ сеанса (заголовок «Cookie: ...» в каждом запросе)
  • Подписанный файл cookie, который хранит информацию о сеансе в самом файле cookie

Там просто один потребитель API прямо сейчас, поэтому я выбрал самую простую вещь, которая могла работать - файлы cookie. Их очень легко использовать в пилонах с помощью Beaker . Они также «просто работают» в приложении Flash - поскольку оно работает внутри браузера, браузер будет включать соответствующие файлы cookie в запросы, которые делает приложение Flash - приложение вообще не нужно изменять в связи с этим. Вот один вопрос StackOverflow, который также поддерживает использование файлов cookie: RESTful-аутентификация для веб-приложений

Beaker также имеет приятную функцию сеансов только для файлов cookie , где все данные сеанса содержатся в самом файле cookie. Я предполагаю, что это практически безгражданство. На сервере нет хранилища сеансов . Файлы cookie подписываются и, при необходимости, зашифровываются, чтобы избежать их подделки на стороне клиента. Недостатком является то, что файл cookie становится немного больше, поскольку теперь он должен хранить больше, чем просто ключ сеанса. Удалив некоторые вещи, которые мне действительно не нужны в сеансе (остатки от аутентификации OpenID), я уменьшил размер cookie примерно до 200 байт.

Файлы cookie подписываются и, при необходимости, зашифровываются, чтобы избежать их подделки на стороне клиента. Недостатком является то, что файл cookie становится немного больше, поскольку теперь он должен хранить больше, чем просто ключ сеанса. Удалив некоторые вещи, которые мне действительно не нужны в сеансе (остатки от аутентификации OpenID), я уменьшил размер cookie примерно до 200 байт.

Файлы cookie подписываются и, при необходимости, зашифровываются, чтобы избежать их подделки на стороне клиента. Недостатком является то, что файл cookie становится немного больше, поскольку теперь он должен хранить больше, чем просто ключ сеанса. Удалив некоторые вещи, которые мне действительно не нужны в сеансе (остатки от аутентификации OpenID), я уменьшил размер cookie примерно до 200 байт.

31
ответ дан 27 November 2019 в 22:38
поделиться

OAuth лучше подходит для использования API. Вот пример использования OAuth в Python: oauth-python-twitter . Библиотека Лии Калвер python-oauth является канонической реализацией OAuth в Python, но python-oauth2 - недавний претендент, который вызывает некоторое оживление. Что касается вдохновения, то django-поршень поддерживает использование OAuth для аутентификации при создании RESTful API для Django, хотя документация по этой конкретной теме не так хороша, как хотелось бы.

4
ответ дан 27 November 2019 в 22:38
поделиться

Если вы создаете API, вы можете проверить протокол OAuth. Он дополняет OpenID.

3
ответ дан 27 November 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: