Централизованно защитите все веб-приложения tomcat с помощью BASIC-аутентификации.

У меня есть сервер Tomcat 6, содержащий три веб-приложения: пользовательское как ROOT, Jenkins и Nexus.

Я хотел бы защитить все три централизованно (server.xml?), используя аутентификацию BASIC.

Как я могу добиться этого без изменения или настройки самих веб-приложений?


person Axel Fontaine    schedule 01.03.2011    source источник


Ответы (4)


Сначала я попытался (безуспешно) включить клапан BasicAuthenticator в conf/context.xml. Это, похоже, не имело никакого эффекта.

Наконец, я заставил его работать (защитил все веб-приложения), добавив этот фрагмент в conf/web.xml :

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Basic Authentication</web-resource-name>
<!--Here wildcard entry defines authentication is needed for whole app -->
            <url-pattern>/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>myrole</role-name>
    </auth-constraint>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
</login-config>

<security-role>
    <description>My role</description>
    <role-name>myrole</role-name>
</security-role>
person Axel Fontaine    schedule 15.03.2011

На ум приходят два способа:

  1. Вы можете изменить файл conf/context.xml, который включается всеми веб-приложениями, и вставить туда директивы аутентификации. Недостатком является то, что вы не можете исключить одно веб-приложение из аутентификации, насколько мне известно, и все веб-приложения будут иметь одинаковые требования к ролям (хотя это звучит так, как вам нужно).
  2. Вы можете реализовать безопасность через apache или какой-либо другой веб-сервер, работающий перед Tomcat. Это имеет смысл, особенно если он у вас уже есть.
person Shay Rojansky    schedule 01.03.2011

Это можно сделать, но над этим нужно поработать.

Для Tomcat в основном вам нужен Tomcat Valve. Это похоже на фильтр сервлетов, но он специфичен для Tomcat.

Вы можете поместить Valve в запись HOST конфигурации вашего сервера, тогда все приложения на этом хосте должны будут проходить через этот Valve. И этот Valve — это то, что вам нужно для обработки вашей BASIC-аутентификации.

У Tomcat уже есть BASIC Authentication Valve, но он предназначен для работы с веб-приложением. Вероятно, вы можете взять исходный код и взломать его, чтобы он работал на уровне хоста, а не на уровне веб-приложения, тем самым защищая все ваши приложения без их индивидуальной настройки.

Теперь, если бы вы были немного более открытыми, я бы предложил Единый вход Tomcat, а затем расширение каждого из веб-приложений для использования BASIC в их файле web.xml в соответствии со спецификацией сервлета. По сути, это тривиальное изменение в файле web.xml отдельных приложений, но оно также решает проблему за вас. Но вы сказали, что не хотите изменять веб-приложения, поэтому вы застряли на использовании конкретных вещей Tomcat и «создаете» их самостоятельно.

person Will Hartung    schedule 02.03.2011
comment
Привет, Уилл, я взял твою идею и соединил ее со скрытой функцией, и все это всего лишь несколько утверждений. Странно, почему это не встроено в BasicAuthenticator... - person mogsie; 29.05.2013

Это возможно, но, насколько мне известно, это невозможно без (некоторого) кода. Вот решение, которое никоим образом не затрагивает развернутые веб-приложения, но которое также не дает вам детальной авторизации, только аутентификацию.

Tomcat 7 (и 6?) имеет отличную функцию для выполнения аутентификации, даже если в веб-приложении нет защищенных ресурсов, называемых preemtiveAuthentication:

<Context preemptiveAuthentication="true">
  <Valve className="org.apache.catalina.authenticator.BasicAuthenticator" />
</Context>

Вставьте это в свой контекст, где бы он ни находился (возможно, вам нужно создать $CATALINA_BASE/conf/Catalina/localhost/mywebapp.xml для защиты mywebapp.war).

Это приведет к тому, что любой входящий запрос с чем-либо в заголовке авторизации вызовет авторизацию. Любой запрос без заголовка Authorization все равно пройдет.

  • http://example.com:8080/mywebapp/ будет работать, а GET /
  • http://user:[email protected]:8080/mywebapp/ не будет (или проверит имя пользователя и пароль)

Таким образом, оставшаяся хитрость состоит в том, чтобы отключать эту "функцию" каждый раз даже для пользователей, которые не отправляют никаких заголовков авторизации. Здесь мне пришлось вернуться к Valve.

Вот код для клапана, который устанавливает заголовок запроса «Авторизация» на «foo», если он отсутствует.

import javax.servlet.ServletException;
import java.io.IOException;
import org.apache.catalina.valves.ValveBase;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

public class ConditionallyAddFakeAuthorizationHeader extends ValveBase {
  public void invoke(Request request, Response response) throws IOException, ServletException {
    if (request.getCoyoteRequest().getMimeHeaders().getValue("authorization") == null) {
      request.getCoyoteRequest().getMimeHeaders().addValue("authorization").setString("foo");
    }
    getNext().invoke(request, response);
  }
}

Скомпилируйте файл, задайте ему хороший пакет, если хотите, и поместите его в общий путь к классам Tomcat, а также добавьте изменения в файл mywebapp.xml следующим образом (добавьте новый клапан перед базовым аутентификатором!):

<Context preemptiveAuthentication="true">
  <Valve className="ConditionallyAddFakeAuthorizationHeader"/>
  <Valve className="org.apache.catalina.authenticator.BasicAuthenticator" />
</Context>

И вуаля, ваш контекст не пропустит ни один запрос, если только он не будет аутентифицирован в определенной вами области.

person mogsie    schedule 29.05.2013