This is an automated email from the ASF dual-hosted git repository.
ashishvijaywargiya pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push:
new 39ec4fda5c Improved: Align tenant resolution between LoginWorker and
ContextFilter (#1835)
39ec4fda5c is described below
commit 39ec4fda5c36094ea902b138a7eb2645f6d5dee4
Author: Krishna Uprit <[email protected]>
AuthorDate: Wed Sep 2 10:58:55 2026 +0530
Improved: Align tenant resolution between LoginWorker and ContextFilter
(#1835)
`ContextFilter` and `LoginWorker` each resolve `userTenantId` for a request
but use opposite precedence, and `ContextFilter` updates the session
`delegatorName` in place when the resolved tenant changes. This makes the two
consistent.
- `LoginWorker.login(...)` now resolves `userTenantId` the same way
`ContextFilter` already does: request attribute first, request parameter
as
fallback. Previously it read the parameter first, so the two could resolve
different tenants for the same request.
- `ContextFilter` now compares the tenant encoded in the session's existing
`delegatorName` (`name#tenantId`) against the tenant resolved for the
current
request. When they differ it invalidates the session, so `dispatcher`,
`security` and `userLogin` are rebuilt for the current tenant on the next
request instead of `delegatorName` alone being overwritten. A warning is
logged when this happens.
No change for single-tenant deployments or when the session tenant and the
request tenant already match.
Thank you Krishna Uprit for the contribution.
Co-authored-by: Krishnauprit18 <[email protected]>
---
.../apache/ofbiz/webapp/control/ContextFilter.java | 26 ++++++++++++++++++++++
.../apache/ofbiz/webapp/control/LoginWorker.java | 8 +++++--
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
index 20b0303113..75f01a7210 100644
---
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
+++
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ContextFilter.java
@@ -30,6 +30,7 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilGenerics;
@@ -143,6 +144,31 @@ public class ContextFilter implements Filter {
tenantId = null;
}
if (UtilValidate.isNotEmpty(tenantId)) {
+ // If an existing session already carries a delegatorName
for a different
+ // tenant than the one resolved for this request,
invalidate it here rather
+ // than only overwriting delegatorName below: dispatcher,
security and
+ // userLogin stay bound to the old tenant otherwise, so a
clean session is
+ // rebuilt on the next request instead. Use
getSession(false) so a request
+ // that has no session yet is left alone - it cannot carry
a stale tenant.
+ HttpSession existingSession =
httpRequest.getSession(false);
+ if (existingSession != null) {
+ String existingDelegatorName = (String)
existingSession.getAttribute("delegatorName");
+ if (UtilValidate.isNotEmpty(existingDelegatorName)) {
+ int hashIndex = existingDelegatorName.indexOf('#');
+ String existingTenantId =
+ hashIndex > 0 ?
existingDelegatorName.substring(hashIndex + 1).trim() : null;
+ if (existingTenantId != null &&
!tenantId.equals(existingTenantId)) {
+ // Log a fixed message only; request-derived
values (host name,
+ // userTenantId) are deliberately kept out of
the log line.
+ Debug.logWarning("Tenant context mismatch: the
session is bound to a"
+ + " different tenant than the one
resolved for this request."
+ + " Invalidating the session so a
clean per-tenant context is"
+ + " rebuilt on the next request.",
MODULE);
+ existingSession.invalidate();
+ }
+ }
+ }
+
// if the request path is a root mount then redirect to
the initial path
if ("".equals(httpRequest.getContextPath()) &&
"".equals(httpRequest.getServletPath())) {
GenericValue tenant =
EntityQuery.use(baseDelegator).from("Tenant").where("tenantId",
tenantId).queryOne();
diff --git
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
index 457a4aef8c..27d91889b0 100644
---
a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
+++
b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
@@ -459,8 +459,12 @@ public final class LoginWorker {
// if a tenantId was passed in, see if the userLoginId is associated
with that tenantId
// (can use any delegator for this, entity is not tenant-specific)
String tenantId = request.getParameter("userTenantId");
- if (UtilValidate.isEmpty(tenantId)) {
- tenantId = (String) request.getAttribute("userTenantId");
+ // Align with ContextFilter: when this request already carries a
resolved userTenantId
+ // attribute (for example from a hostname mapped to a tenant), that
value wins over a
+ // conflicting request parameter, so both components authenticate
against the same tenant.
+ String requestTenantId = (String) request.getAttribute("userTenantId");
+ if (UtilValidate.isNotEmpty(requestTenantId)) {
+ tenantId = requestTenantId;
}
if (UtilValidate.isNotEmpty(tenantId)) {
// see if we need to activate a tenant delegator, only do if the
current delegatorName has a hash symbol in it,