Protokół przy przekierowaniu serwletowym w WebLogic
Dla niektórych kodów stanu HTTP przeglądarka automatycznie przekierowuje użytkownika do miejsca wskazanego przez nagłówek "Location" zwracany w odpowiedzi zapytania.
Kody wyzwalające automatyczne przekierowanie zaczynają się od cyfry 3. W przypadku interfejsu serwletowego w Javie, tj.
javax.servlet.http.HttpServletResponse.sendRedirect(String)
, będzie to najczęściej status 302.
Podczas migracji aplikacji serwletowej z serwera takiego jak Tomcat na serwer WebLogic możesz napotkać na pewną funkcjonalność, która sprawia, że nagłówek "Location" zostanie uzupełniony wartością absolutną wraz z protokołem. Niestety, funkcjonalność ta często gryzie się z reverse-proxy, które to terminuje ruch SSL i komunikuje się z serwerem WebLogic przy wykorzystaniu niezabezpieczonego portu HTTP.
WebLogic a przekierowanie względnej lokalizacji na bezwzględny adres URL
Sytuację, w której WebLogic standardowo przekieruje do lokalizacji HTTP przy użyciu protokołu HTTPS, można łatwo zasymulować
przy użyciu reverse-proxy nginx bądź Apache.
Załóżmy, że wysyłamy zapytanie POST do https://example.com/app/foo, czyli serwletu WebLogic wywołującego sendRedirect("bar")
zza reverse-proxy:
# Nagłówki żądania (zbędne nagłówki zostały pominięte)
POST /app/foo HTTP/1.1
Host: example.com
Origin: https://example.com
Referer: https://example.com/bar
Żądanie wychodzące od reverse-proxy:
POST /app/foo HTTP/1.1
Host: [example.com]
X-forwarded-host: [example.com]
Upgrade-insecure-requests: [1]
X-forwarded-server: [example.com]
X-forwarded-for: [192.168.0.100]
X-forwarded-proto: [https]
X-forwarded-ssl: [on]
Mimo że reverse-proxy dołożyło nagłówki X-forwarded-*
pozwalające na skonstruowanie poprawnego adresu zwrotnego, WebLogic odpowie zasobem HTTP zamiast HTTPS:
HTTP/1.1 302 Moved Temporarily
Location: http://example.com/app/bar
Rozwiązanie problemu mixed-content przy przekierowaniu
Problem możemy rozwiązać na kilka różnych sposobów:
- przepisując nagłówek odpowiedzi na serwerze proxy;
- implementując niestandardowy filtr, który przepisze nagłówek odpowiedzi przy wyjściu z WebLogica;
- włączając opcję "WebLogic Plugin Enabled" w konsoli WebLogic i dodając nagłówek żądania "WL-Proxy-SSL: ON” na serwerze proxy;
- ustawiając "WL front end host" i port w konsoli WebLogica.
Zaciekawiony, dlaczego standardowe nagłówki nie są obsługiwane, zerknąłem wewnątrz dostarczonej biblioteki serwletów WebLogica. Szybko jednak zdałem sobie sprawę, że najbezpieczniejszym i najprostszym rozwiązaniem jest po prostu wyłączenie bezwzględnego uzupełniania adresu URL podczas przekierowania.
Do zweryfikowania działania umieściłem breakpoint na metodzie
sendRedirect()
, i wywołałem w debuggerzegetClass().getProtectionDomain().getCodeSource().getLocation()
. Mając lokalizację implementacjiHttpServletResponse
, dodałem ją do ścieżki klas w moim IDE: /u01/oracle/wlserver/modules/com.oracle.weblogic.servlet.jar!/weblogic/servlet/internal/ServletResponseImpl.class (z oficjalnego obrazu dockerowego wersji WebLogic 12.1.2.4).
Okazuje się, że możemy to zrobić w deskryptorze aplikacji internetowej WEB-INF/weblogic.xml
. Pamiętaj aby zamienić wersję XSD 1.9
na
pasującą do Twojego WebLogica:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app
http://xmlns.oracle.com/weblogic/weblogic-web-app/1.9/weblogic-web-app.xsd">
<context-root>/app</context-root>
<container-descriptor>
<redirect-with-absolute-url>false</redirect-with-absolute-url>
</container-descriptor>
</weblogic-web-app>
Komentarz z pliku XSD: Jeśli element
redirect-with-absolute-url
jest ustawiony nafalse
, wówczas kontener serwletu nie przekonwertuje względnego adresu URL na bezwzględny adres URL w nagłówku lokalizacji w przekierowaniu.