<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">пт, 1 янв. 2021 г. в 22:47, Vladislav Shabanov <<a href="mailto:vlad.shabanov@gmail.com">vlad.shabanov@gmail.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;">Добрый день!<div><br></div><div>Хочу посоветоваться.</div><div>Есть сервер, где зона «для сотрудников» закрыта двумя слоями авторизации:</div><div><span style="white-space:pre-wrap"> </span>auth_basic</div><div><span style="white-space:pre-wrap"> </span>+ проверка на уровне приложения, с куками, сессиями и прочим.</div><div><br></div><div>Отказываться от auth_basic не хочется: </div><div><ul><li>В коде приложения запросто могут быть ошибки. Забыли, например, завернуть какую-нибудь функцию приложения в декоратор и получили дырку в защите.</li><li>Сессионную куку могут угнать. XSS, «мутные» плагины для браузеров и т. д.</li><li>Есть «интимная» статика, которую проверять через auth_request не хочется, т.к. замедляет.</li></ul></div><div>Проблема в том, что большинство браузеров неудобно работают с basic_auth: Сафари под iPhone спрашивает пароль каждые несколько часов и даже не заморачивается, чтобы его запомнить. FireFox после рестарта показывает модальный диалог со вводом пароля в одном из окон и блокирует все остальные окна с тем же сайтом. Неудобно, короче.</div><div><br></div><div>Настроил клиентские сертификаты. Есть сотни мануалов, ничего интересного. Но вот раздача сертификатов сотрудникам и установка их в браузеры – дело муторное. У каждого браузера свои тараканы, сложно объяснить сотруднику по телефону, как поставить сертификат в его браузер и т. д. А если сертификат устареет или придётся его отозвать, совсем беда.</div><div><br></div><div>Поэтому решил сделать вот какую логику:</div><div><ul><li>Если браузер предъявил сертификат, то <i>auth_basic</i> не требуем.</li><li>Если не предъявил, то пусть вводит логин+пароль через <i>auth_basic</i>.</li><li>Проверка доступа на уровне приложения никуда не девается, работаем по старому.</li></ul></div></div></blockquote><div><br></div><div>тут есть подводные камни как минимум с сафари.</div><div>браузер предъявил или браузер не предъявил на транспортном уровне работает таким образом</div><div><br></div><div>1) в серверном SSL Hello выставляется флаг "хочу сертификат"</div><div>(вы можете намекнуть клиенту, на каких именно УЦ вы хотели бы видеть сертификат, либо "<code><strong>ssl_verify_client</strong><code></code><code></code><code></code> <code>optional_no_ca</code>;", если вы готовы принимать сертификат любого УЦ)</code></div><div><code><br></code></div><div><code>2) нормальный браузер реагирует так, если он видит, что у него нет клиентских сертификатов на требуемом УЦ, он не пытается спросить у пользователя, и отправляет запрос без сертификата</code></div><div><code><br></code></div><div><code>3) сафари будет требовать пользователя сертификат в любом случае</code></div><div><code><br></code></div><div><code>далее на стороне nginx можно настроить обработчик 496 ошибки, мы с таким игрались, туда попадет трафик без клиентских сертов (и там вы сможете реализовать нужную вам логику)<br></code></div><div><code><br></code></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;"><div>Я не нашёл способа, как настроить конфиг nginx, чтобы эту логику реализовать. Конструкции с</div><blockquote style="margin:0px 0px 0px 40px;border:medium none;padding:0px"><div>if $ssl_client_verify == "SUCCESS" {}</div></blockquote><div>несовместимы с auth_basic.</div></div></blockquote><div><br></div><div><br></div><div>error_page 496 .....<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;"><div><br></div><div>Пока придумал только одно: отпатчил <i>ngx_http_auth_basic_module.c</i>, сделал в нём директиву</div><blockquote style="margin:0px 0px 0px 40px;border:medium none;padding:0px"><div><i>auth_basic_skip_if_client_cert</i> <i>on/off</i></div></blockquote>по которой проверка пароля выключается, если предъявлен валидный клиентский сертификат.<div><br></div><div>Вопросы:</div><div><ol><li>Может быть, кто-то решал аналогичную задачу? Чтоб и два слоя защиты для страховки и удобство в повседневной работе?</li></ol></div></div></blockquote><div><br></div><div>кроме описанной вами трудностей с доставкой и установкой клиентских сертов еще есть неприятное поведение сафари<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;"><div><ol><li>Существует ли решение без патча ngx_http_auth_basic_module.c?</li><li>Интересен ли кому-нибудь этот патч? Может, на моём велосипеде ещё кто-нибудь хочет покататься? :) </li></ol></div></div></blockquote><div><br></div><div>как-то сейчас oauth более в тренде<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;"><div><br></div><div>С уважением,</div><div><span style="white-space:pre-wrap"> </span>Владислав</div><div><br></div><div><br></div><div><br></div></div>_______________________________________________<br>
nginx-ru mailing list<br>
<a href="mailto:nginx-ru@nginx.org" target="_blank">nginx-ru@nginx.org</a><br>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-ru" rel="noreferrer" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-ru</a></blockquote></div></div>