Передайте имя пользователя и сертификат клиента из apache в tomcat, используя mod_jk - PullRequest
3 голосов
/ 04 октября 2019

Я хочу аутентифицировать веб-сервисы либо с помощью ssl сертификата (нацеленного на автоматизацию), либо openid (нацеленного на людей, я использую auth0 в качестве провайдера). Веб-службы работают в контейнере Tomcat, который находится за веб-сервером Apache, используя jk. Веб-сервер уже аутентифицирует пользователя, используя auth0 (используя mod_auth_openidc) для других путей и доступный только через https. У меня также есть база данных, которая в настоящее время сопоставляет имена пользователей, предоставленные auth0, с ролями (используется для авторизации в apache).

Мне бы хотелось иметь следующие функции:

  1. выяснить имя пользователя
    • , если apache уже вошел в систему пользователя, используйте имя пользователя
    • , если в запросе используется сертификат клиента, используйте DN в качестве имени пользователя
    • , если ничего из вышеперечисленного,затем перенаправить, чтобы apache выполнил аутентификацию
  2. и выяснил роль
    • при поиске в базе данных на основе имени пользователя

Я понял, что мне, возможно, придется написать фильтр, и из прокси-документации jk кажется, что я могу получить сертификат и имя пользователя из запроса. Я написал следующий код:

package com.kodekonveyor.realm;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class KKAuthorizationFilter implements Filter {

private ServletContext context;

@Override
public void init(FilterConfig fConfig) throws ServletException {
    this.context = fConfig.getServletContext();
    this.context.log("KKAuthorizationFilter initialized");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    String user = httpRequest.getRemoteUser();
    Object cert = httpRequest.getAttribute("javax.servlet.request.X509Certificate");
    this.context.log("user:"+user);
    this.context.log("cert:"+cert);
    chain.doFilter(request, response);

}

}

Однако, когда я пытаюсь связаться с сервлетом с пользователем, который в данный момент аутентифицирован, или с аутентификацией ssl клиента, и пользователь, и сертификат регистрируются как нулевые. Я подозреваю, что мне нужно сделать еще несколько настроек Apache, чтобы заставить его работать. Тестовый сервлет находится в / servlet / servlet в tomcat.

У меня есть следующая конфигурация apache (части для пивоварения не указаны)

DocumentRoot /var/www/repo

#correct OIDC configuration omitted

<VirtualHost myhost.mydomain.com:443>
    ServerName myhost.mydomain.com

DBDriver pgsql
#other DBD configurations are omitted

JkMount /servlet* worker1

<Directory /var/www/repo/servlet>
    DirectoryIndex off
    RewriteEngine Off
    AuthType openid-connect
    AllowOverride None
    AuthzDBDQuery "a correct database query"
    Require dbd-group allrepo
LogLevel debug
</Directory>

<Directory /var/www/repo>
    DirectoryIndex off
    RewriteEngine Off
    AllowOverride None
</Directory>

#correct letsencrypt configuration omitted
</VirtualHost>

1 Ответ

1 голос
/ 08 октября 2019

Причина в том, что если у вас есть директива JkMount в местоположении (или, возможно, также в каталоге), все остальные директивы авторизации и авторизации (или даже все другие?) Неэффективны.

Пример рабочей конфигурации для сервлета, расположенного в / servlet:

<Location "/servlet*">
        JkMount  worker1
</Location>
<LocationMatch /servlet.*>
    DirectoryIndex off
    RewriteEngine Off
    AuthType openid-connect
    AllowOverride None
    LogLevel debug
    Require valid-user
        SSLOptions +StdEnvVars
        SSLOptions +ExportCertData
        SSLVerifyClient require
</LocationMatch>

другое возможное решение:

<LocationMatch /servlet.*>
       SetHandler jakarta-servlet
       SetEnv JK_WORKER_NAME worker1
       DirectoryIndex off
       RewriteEngine Off
       AuthType openid-connect
       AllowOverride None
       Require valid-user
       LogLevel debug
        SSLOptions +StdEnvVars
        SSLOptions +ExportCertData
        SSLVerifyClient require
</LocationMatch>

См. https://tomcat.markmail.org/thread/iax6picwsjlhbohd для обсуждения

...