Как использовать System.IdentityModel в собственном клиент-серверном приложении

У меня есть простое клиент-серверное приложение на основе TcpClient/TcpListener и SslStream. Клиенты могут аутентифицироваться на сервере с помощью сертификата X509 или путем отправки имени пользователя и пароля после того, как был установлен SslStream.

WCF использует пространство имен System.IdentityModel для целей аутентификации, но очевидно, которое может использоваться в произвольных приложений - это звучит интересно. Информация о том, как это сделать, разрежена (или мой Google foo сегодня слаб).

Итак, мой вопрос: Что мне нужно сделать для интеграции System.IdentityModel с моим приложением? Я не уверен, что мне нужен весь этот материал ClaimSet, но было бы неплохо, если бы пользователи могут войти в систему, просто используя свою учетную запись Windows или любой другой механизм аутентификации. (К сожалению, я не могу просто переключиться на WCF, но должен использовать настраиваемый протокол, хотя я могу внести в него некоторые изменения, если это необходимо.)

Ответы

Ответ 1

Мой Google foo был действительно слабым. Ответ прямо позади ссылки в моем вопросе. Итак, вот несколько ссылок на этот блог, если кто-то имеет тот же вопрос в конце концов.

Во-первых, вы должны попытаться понять "этот набор требований":

Затем вам нужно знать, откуда возникают претензии:

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

Если я правильно ее понимаю, основной рабочий процесс будет примерно таким:

  • Клиент создает SecurityToken с помощью SecurityTokenProvider
  • Клиент выполняет сериализацию SecurityToken с помощью SecurityTokenSerializer
  • Сервер десериализует SecurityToken с помощью SecurityTokenSerializer
  • Сервер создает IAuthorizationPolicy с помощью SecurityTokenAuthenticator
  • Сервер создает AuthorizationContext из IAuthorizationPolicy s
  • Готово

Пример:

// Create the SecurityTokenProvider
var p = new UserNameSecurityTokenProvider("username", "password");

// Get the SecurityToken from the SecurityTokenProvider
var t = p.GetToken(TimeSpan.FromSeconds(1.0)) as UserNameSecurityToken;

// ... transmit SecurityToken to server ...

// Create the SecurityTokenAuthenticator
var a = new CustomUserNameSecurityTokenAuthenticator(
    UserNamePasswordValidator.None);

// Create IAuthorizationPolicies from SecurityToken
var i = a.ValidateToken(t);

// Create AuthorizationContext from IAuthorizationPolicies
var c = AuthorizationContext.CreateDefaultAuthorizationContext(i);
ShowClaims(c.ClaimSets);

Для X509SecurityToken используйте X509SecurityTokenProvider/Authenticator. Для WindowsSecurityToken существует a WindowsSecurityTokenAuthenticator, но не поставщик; вместо этого используйте конструктор WindowsSecurityToken:

var t = new WindowsSecurityToken(WindowsIdentity.GetCurrent());

Это работает довольно хорошо. Единственное, что я пропустил выше, это сериализация маркера. Существует класс SecurityTokenSerializer, который имеет одну реализацию в .NET framework: класс WSSecurityTokenSerializer, который поставляется с WCF.

Сериализация UserNameSecurityToken и X509SecurityToken работает как шарм (не пробовали десериализацию), но WindowsSecurityToken, по-видимому, не поддерживается сериализатором. Это оставляет мне два метода проверки подлинности, которые у меня уже есть (сертификаты и имя пользователя/пароль), и, поскольку я не хотел, чтобы это AuthorizationContext в любом случае, я буду придерживаться того, что у меня есть:)

Ответ 2

У меня нет репутации, чтобы опубликовать комментарий к существующему решению, но я бы хотел опубликовать новые URL-адреса в блогах, перечисленных в решении, поскольку они больше не работают. Если кто-то может изменить это на комментарий, я был бы очень обязан.