Запуск двух приложений Spring Boot за Nginx с SSI - PullRequest
1 голос
/ 07 мая 2020

Короче - у меня есть два приложения Spring Boot с аутентификацией Keycloak, работающие за Nginx, и я хотел бы использовать содержимое App2 в App1 через SSI. Кроме того, требуется единый вход, поэтому нет необходимости входить в оба приложения по отдельности.


Моя настройка следующая:

  • Два приложения Spring Boot (App1 и App2), работающие на портах localhost 9000 и 9001 соответственно, обслуживают разметку HTML, которую можно включить в SSI для создания финальной страницы. Оба приложения безопасны и требуют, чтобы пользователь вошел в систему. App1 имеет свой контекст root в /, App2 имеет его в /app2
  • Сервер Keycloak для управления аутентификацией пользователя с использованием OID C . И App1, и App2 настроены для связи с сервером с помощью Spring Security Keycloak Adapter и зарегистрированы как один клиент в Keycloak
  • Я использую Nginx в качестве обратного прокси, с которым сталкивается пользователь. SSI включен. Приложение 1 и Приложение 2 зарегистрированы под двумя отдельными locations в конфигурации Nginx. См. Файл nginx.conf ниже.

Вариант использования, которого я пытаюсь достичь:

  • Приложение 1 обслуживает страницу HTML, которая по сути является "оболочкой" приложения - содержит макет и заголовок, нижний колонтитул. В области содержимого есть директива SSI include virtual, которая извлекает содержимое из App2.
  • Итак, в конце концов, я хочу увидеть страницу, обслуживаемую App1, с содержимым из App2.
  • Очевидно, что оба приложения требуют входа в систему, но поскольку у меня настроен Keycloak и оба приложения используют одну и ту же область K C и идентификатор клиента, входа в любое из них должно хватить

Что происходит:

  • Как только я нажимаю App1, я еще не вошел в систему, я вижу приложение оболочки без какого-либо защищенного содержимого из App1 или App2. Это хорошо.
  • Как только я вхожу в приложение App1, JSESSIONID устанавливается с помощью cook ie по пути /. Однако контент из App2 не отображается [который должен был исходить из включения SSI]
  • Когда я go перехожу на страницу, обслуживаемую App2, оно мгновенно распознает пользователя, и нет необходимости повторно входить в систему, и обслуживается весь защищенный контент. App2 работает нормально. App2 также сохраняет JSESSIONID cook ie по пути /app2.

То, что я пробовал до сих пор:

  • Пробовал Nginx готовить ie переписывание пути для сохранения обоих файлов cookie по пути /. Это приводит к тому, что два файла cookie конфликтуют и сбрасывают друг друга.
  • Пытался зарегистрировать App1 и App2 как отдельных клиентов в Keycloak
  • Я знаю, что когда страница оболочки, обслуживаемая App1, читается процессор SSI в Nginx, ему необходимо сделать запрос к App2 для заполнения содержимого SSI, но для этого ему нужны соответствующие файлы cookie для App2, чтобы проверить запрос. Пробовал использовать для этого несколько методов проб и ошибок.

Что-то не так с вариантом использования, которого я пытаюсь достичь, или что-то я делаю не так? Spring / Java / Keycloak / Nginx здесь новичок, заранее спасибо.


nginx.conf файл :

worker_processes  1;
events {
    worker_connections  1024;
}

error_log logs/error.log warn;

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;
        ssi on;
        client_max_body_size 100M;
        port_in_redirect off;

        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-App-Proto  http;
        proxy_set_header X-Forwarded-App-Port  80;

        # For App1
        location / {
            proxy_pass http://localhost:9000;
        }

        # For App2
        location /app2/ {
            # Notice no trailing / - it means whole URL will be preserved
            # i.e., "/app2" will not be discarded from the URL sent to proxy
            # which is what we want as our spring app has context root at "/app2"

            proxy_pass http://localhost:9001;

            # proxy_cookie_path ~*^/.* /; -- This results in conflicts in the two JSESSIONID cookies
        }

        error_page   302 404 500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

application.yml файлы приложений App1 и App2:

server:
  servlet:
    contextPath: /app2 # this is just '/' for App1
  port: 9001 # this is 9000 for App1
  use-forward-headers: true
  tomcat:
    protocol-header: X-Forwarded-App-Proto
    port-header: X-Forwarded-App-Port


########## Keycloak configuration
keycloak:
  auth-server-url: http://localhost:8080/auth
  realm: AppRealm
  resource: AppClient
  public-client: true
  principal-attribute: preferred_username
security:
  disable-csrf: true
...