Используем сертификаты x.509 в apache
Была у меня на работе задачка — сделать авторизацию пользователей на сайте через сертификаты X.509. Вроде бы, всё просто – погуглил, почитал, оказалось, десятки разных статей и все противоречат друг другу.
Создание сертификатов
Первое, что сделаем, это создадим серверный и клиентские сертификаты. Нужна програмка openssl.exe (у меня установлен xampp, в нём есть всё, что нужно – вам его тоже советую). Итак, в папке /сервер/apache/bin находим openssl.exe и создаём файлы ca.config и openssl.cnf. Также, создадим папку db, а в ней папки certs, newcerts, пустые текстовые файлы index.txt и serial (внутри этого файла написать “01” без ковычек.)
Содержимое файла ca.config
[ ca ] default_ca = CA_CLIENT # При подписи сертификатов # использовать секцию CA_CLIENT [ CA_CLIENT ] default_days = 365 # Срок действия подписываемого policy = policy_anything # Название секции с описанием [ policy_anything ] |
Содержимое файла openssl.cnf
# ================================================= # OpenSSL configuration file # ================================================= RANDFILE = .rnd [ ca ] default_ca = CA_default [ CA_default ] dir = . certs = $dir new_certs_dir = $dir crl_dir = $dir database = $dir/db/index.txt private_key = $dir/ca.key certificate = $dir/ca.crt serial = $dir/db/serial crl = $dir/crl.pem RANDFILE = $dir/db/private/.rand default_days = 365 default_crl_days = 30 default_md = sha1 preserve = no policy = policy_anything name_opt = ca_default cert_opt = ca_default [ policy_anything ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] default_bits = 1024 default_md = sha1 default_keyfile = privkey.pem distinguished_name = req_distinguished_name x509_extensions = v3_ca string_mask = nombstr [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [ usr_cert ] basicConstraints = CA:FALSE # nsCaRevocationUrl = https://url-to-exposed-clr-list/crl.pem [ ssl_server ] basicConstraints = CA:FALSE nsCertType = server keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, nsSGC, msSGC nsComment = «OpenSSL Certificate for SSL Web Server» [ ssl_client ] basicConstraints = CA:FALSE nsCertType = client keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = clientAuth nsComment = «OpenSSL Certificate for SSL Client» [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment [ v3_ca ] basicConstraints = critical, CA:true, pathlen:0 nsCertType = sslCA keyUsage = cRLSign, keyCertSign extendedKeyUsage = serverAuth, clientAuth nsComment = «OpenSSL CA Certificate» [ crl_ext ] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment nsComment = «OpenSSL generated CRL» |
открываем cmd.exe (Пуск –> Выполнить –> cmd –> enter), далее запускаем через cmd программу openssl.exe и приступаем непосредственно к созданию наших сертификатов.
1) создаём серверный ключ и сертификат
req -new -x509 -days 365 -sha1 -newkey rsa:1024 -nodes -keyout server.key -out server.crt -subj ‘/O=НазваниеКомпании/OU=Подразделение/CN=localhost’
Укажите здесь название вашей компании, подразделения, а также доменное имя.
2) создаём CA сертификат для авторизации пользователей
req -config openssl.cnf -new -x509 -days 3652 -sha1 -newkey rsa:1024 -keyout ca.key -out ca.crt -subj ‘/O=Организация/OU=Подразделение’
Укажите здесь название вашей компании, подразделения.
3) создаём пользовательские сертификаты
- req -new -sha1 -newkey rsa:1024 -nodes -keyout server.key -out request.pem -subj ‘/O=Skif Grid/OU=PSI RAS/CN=localhost’
- ca -config openssl.cnf -policy policy_anything -extensions ssl_server -out signed.pem -infiles request.pem
- x509 -in signed.pem -out server.crt
- openssl pkcs12 -export –in signed.pem –inkey server.key -certfile ca.crt -name «Имя\Отчество» -out user.p12
Получившееся ca.crt и user.p12 импортируем в браузер. С сертификатами покончено, теперь пришло время Apach’a.
Настройка Apache
Открываем файл /сервер/apache/conf/extra/httpd-ssl.conf, стираем всё, что там есть и копируем туда следующее:
ErrorLog D:/www/apache/logs/ssl_error.log LogLevel warn Listen 443 AddType application/x-x509-ca-cert .crt .pem SSLPassPhraseDialog builtin NameVirtualHost *:443 <VirtualHost _default_:443> AddDefaultCharset utf-8 DocumentRoot «D:/www/htdocs» SSLEngine on SSLCertificateFile conf/ssl/server.crt SSLVerifyClient require SSLProxyEngine off <Location /> </Location> |
Если мы хотим сделать авторизацию не обязательной (скажем, чтобы, если у пользователя не будет сертификата, то показать ему красивую страничку с надписью, скажем – получите сначала сертификат), то SSLVerifyClient поставьте как optional.
В папке /сервер/apache/conf/ создадим папку ssl. В неё скопируем созданные нами чуть раньше файлы server.crt, server.key, ca.crt
Проверяем
Если сервер был запущен – перезапустите его. Создадим простенькую страничку на php со следующем кодом:
<? echo “<pre>”; print_r($_SERVER); echo “</pre>”; ?> |
Сохраним, и зайдём на неё через https, т.е, скажем так: https://localhost/ssl_try.php
Браузер должен показать вам окно выбора сертификата. Если SSLVerifyClient установлен как require, то при неправильном сертификате браузер выдаст вам страницу с ошибкой.
Если же всё прошло хорошо, то мы увидим нашу страницу со всеми серверными переменными, включая SSL_CLIENT_CERT, в котором хранится клиентский сертификат (из неё же можно будет вытащить, при необходимости, нужные нам данные – имя, организация, email и т.д.)