Эта статья задумывалась как практическое руководство по установке и настройке сервера JASIG CAS. Я не ставил себе целью объяснить, что такое Single Sign On (SSO), поэтому если вы еще не знакомы с этим понятием, то сначала загляните на википедию и портал Techtarget. Желательно, также иметь опыт работы со Spring и Maven.
Статья будет состоять из 3-х частей. В начале я коротко расскажу, почему мы остановили свой выбор на CAS и об особенностях его протокола. Остальная статья будет посвящена настройке сервиса авторизации, начиная с конфигурации контейнера сервлетов и заканчивая решением некоторых нетривиальных вопросов, таких как авторизация с внешней формы и хэширование учетных данных.
Почему JASIG CAS
Существует много реализаций идеи единой авторизации, и я не могу сказать, что JASIG CAS во всем лучше своих аналогов, тем не менее, по ряду причин, мы остановились на нем.
- Стек технологий JAVA. CAS полностью написан на JAVA с применением Spring. Для сборки используется Maven.
- Open Source.
- Поддержка нескольких реализаций LDAP.
- Активное сообщество. Приятные портал JASIG и вики, есть много статей в сети.
- Клиенты под все популярные платформы. Подробнее можно посмотреть вот тут.
- Поддержка разных способов аутентификации.
- Частые релизы.
- Относительная простота настройки. Я надеюсь, что благодаря этой статье, она станет действительно простой и понятной.
Если вы выбираете платформу для SSO по тем же критериям, то CAS, именно то, что вы ищете.
Как это работает
Мы взяли за основу нашего SSO сервиса, CAS, работающий по протоколу второй версии. Подробно об этом протоколе можно прочитать на портале JASIG. Чуть ниже приведена схема процесса, удачной авторизации в CAS. Подобной схемы на портале JASIG я не нашел, хотя, мне кажется, она должна оказаться полезной для понимания процесса.
Легенда
- Клиент — браузер пользователя. Не путать с CAS клиентом.
- Приложение — это одно из ваших приложений, имеющих на борту CAS клиент и использующих для авторизации CAS сервер.
- CAS — сервер или кластер с развернутым на нем SSO сервисом.
- ST — service ticket. Представляет собой строку, которая используется как учетные данные клиента для доступа к сервису. Клиент получает его в ответ на, предоставленные CAS серверу, учетные данные и идентификатор сервиса.
- TGT (ticket granting ticket) и TGC( ticket granting cookie). TGT представляет собой строку, служащую индикатором авторизованного состояния клиента. После авторизации она заменяет собой учетные данные клиента. Значение TGT храниться в TGC установленной сервером CAS, после успешной авторизации клиента.
- LT ( login ticket). Строка, передающаяся вместе с учетными клиента. Используется для того, что бы исключить повторную обработку учетных данных.
- SAML ( The Security Assertion Markup Language) — основанный на XML язык, разработанный OASIS. Подробности можно узнать на сайте сообщества
Обратите внимание, что все запросы к SSO серверу должны быть по HTTPS. Это не требование протокола, однако, без этого невозможно обеспечить безопасность учетных данных пользователя.
Еще одной важной особенностью протокола является то, что во время проверки значений ST + TGT, CAS клиент, установленный в авторизуемом сервисе, останавливает исходный запрос и создает новый. Т.е. в этот момент клиентом для CAS сервера является не браузер пользователя, а авторизуемый сервис. Это значит, что для создания HTTPS соединения сервис должен быть правильно настроен. Как это сделать я напишу чуть позже. Обработка исходного запроса возобновиться только после завершения проверочного.
Cервера, ключи, проблемы
В качестве контейнера сервлетов мы выбрали Tomcat. Информация о пользователях храниться в openLDAP, а в качестве CAS клиента для приложений чаще всего используем официальный java клиент. На момент написания статьи последняя версия была 3.1.
Настройка SSO начинается с конфигурации контейнеров сервлетов. В тестовой и боевой средах, мы делаем это немного по-разному.
В тестовом окружении с помощью утилиты keytool нужно создать самоподписанный сертификат. Keytool — это стандартная утилита, которая входит в состав любого JDK.
keytool -genkey -alias cas -keypass 12345678 -keystore ssoServer.jks -storepass 12345678 -dname «cn=localhost, ou=webdev, o=ourOrganisation, c=RU» -validity=365
В результате у нас будет создан keystore ssoServer.jks и пара ключей, приватный и публичный. Теперь из keystore можно экспортировать публичный ключ
keytool -export -alias cas -file casServerPublic.cer -keystore ssoServer.jks -storepass 12345678
и, импортировать его в хранилища доверенных сертификатов, для всех сервисов, которые будут участвовать в единой авторизации. На PC команда выглядит вот так:
keytool -import -alias cas -file %PATH_TO%casServerPublic.cer -keypass 12345678 -keystore JAVA_HOME/jre/lib/security/cacerts cacerts -storepass changeit
На Маке так:
# /Library/Java/Home/bin/keytool -import -alias cas -file %PATH_TO_CERTIFICATE%/casServerPublic.cer -keypass 12345678 -keystore /Library/Java/Home/lib/security/cacerts -storepass changeit
Импорт ключей нужен для того, что бы авторизуемый сервис мог установить HTTPS соединение с CAS. Перед тем как импортировать ключи убедитесь, что
- Вы используете JAVA нужной версии. Если у вас установлено несколько версий — могут возникнуть проблемы.
- Используете Keytool и путь cascerts именно той java, которую будете использовать для запуска авторизуемого сервиса.
- У вас есть права на импорт ключей в хранилище.
В результате вы должны увидеть сообщение:
Certificate was added to keystore.
Если сообщение выглядит не так или за ним следует какой-либо текст, это значит, что вы сделали что-то не так, и ключ, скорее всего, не был импортирован.
В боевой среде вы, скорее всего, будете использовать ключи, предоставленные одним, из широко известных CA, таким как Thawte или Verisign. В этом случае ключи будут в формате pkcs#7 или x.509 и вам нужно будет предварительно конвертировать их в формат pkcs#12.
Например, для сертификатов в формате X.509 (Base64) нужно выполнить следующую последовательность шагов:
- Склеиваем все промежуточные сертификаты в один файл. В нем первым должен быть ваш сертификат, а затем вся промежуточная цепочка по порядку.
- Конвертируем его с помощью OpenSSL в нужный формат.
openssl pkcs12 -export —in your.crt —inkey your.key —out your.p12 -name «cas»
- Проверяем, что пара ключей создана правильно
keytool —keystore your.p12 -storetype pkcs12 —list
- И последний шаг — создаем keystore на основе пары ключей
keytool -importkeystore -deststorepass 12345678 -destkeypass 12345678 -destkeystore ssoServer.jks -srckeystore your.p12 -srcstoretype PKCS12 -srcstorepass 12345678 -alias cas
Хранилище публичных сертификатов по умолчанию имеет пароль changeit. В боевой среде его нужно поменять.
Осталось настроить коннектор на tomcat, на котором будет расположен CAS. Для этого в файл %TOMCAT-HOME%/conf/server.xml добавляем описание коннектора, например так:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keyAlias="cas" keystoreFile="%PATH_TO%.ssoServer.jks" keystorePass="12345678" />
Подробнее о настройке коннекторов можно прочитать на странице документации.
В боевой среде HTTP коннектор из server.xml лучше удалить о греха по дальше).
На этот раз все. В следующей части я расскажу как настроить и собрать CAS сервер.
Автор: SergeyPopov