You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OFBiz中SAML2重定向后跨WebApp会话丢失问题求助

Hey there, let's work through your SAML2 cross-webapp session issue in OFBiz step by step. I’ve dealt with similar multi-module session problems in OFBiz before, so here’s how to approach this:

Recap of Your Problem

You’ve implemented SAML2 via a custom SAMLIntegration plugin in OFBiz:

  • The plugin hosts your ACS (ofbizwebsite.com/SAMLIntegration/control/acs) and metadata endpoints
  • Your checker WebEvent handler validates user sessions
  • Sessions work fine within the SAMLIntegration plugin, but are lost when navigating to other OFBiz webapps (like ofbizwebsite.com/aplugin/control/anotherview)
  • You want to replace OFBiz’s built-in externalKey UUID mechanism with SAML2, but you’re stuck on how to trigger a SAML request from the checker handler and return control to the original requested resource after authentication.

Core Issue to Solve

SAML2’s SP-initiated flow works by redirecting the user to the IdP, then back to your ACS. The problem is that this redirect breaks the context of the original request (the aplugin resource the user was trying to access). You need to:

  1. Save the original request context before redirecting to the IdP
  2. Restore that context after the ACS processes the IdP’s response
  3. Ensure user session data is accessible across all OFBiz webapps

Step-by-Step Solutions

1. Persist Original Request Context Before SAML Redirect

When your checker handler detects no valid user session:

  • Capture the full URL of the original request (including query parameters)
  • Store this URL in a global, cross-webapp cache (OFBiz’s SimpleCache is perfect for this— it’s designed for shared state across modules)
  • Generate a unique temporary ID to associate with the stored URL
  • Pass this temporary ID as the RelayState parameter in your SAML AuthnRequest (SAML standard guarantees the IdP will send this value back to your ACS unmodified)

2. Unify ACS Handling & Redirect Back to Original Resource

You don’t need separate ACS endpoints for each webapp— keep using your existing SAMLIntegration/control/acs. Here’s what to do in the ACS handler:

  • Validate the SAML response from the IdP and retrieve the user’s identity (e.g., NameID)
  • Create or fetch the corresponding UserLogin entity in OFBiz
  • Store the UserLogin in a cross-webapp cache (again, SimpleCache works) and associate it with the user’s SAML NameID
  • Set a domain-wide cookie (with domain=ofbizwebsite.com and path=/) containing the SAML NameID— this lets all webapps access the user’s identity
  • Retrieve the temporary ID from the RelayState parameter, fetch the original request URL from the cache, and redirect the user back to that URL

3. Update the checker Handler to Use Cross-Webapp Session Data

Modify your checker handler to:

  • First check the current webapp’s session for a UserLogin
  • If none exists, check the domain-wide SAML cookie for the NameID
  • Use the NameID to fetch the UserLogin from the cross-webapp cache
  • If found, populate the current webapp’s session with the UserLogin to avoid re-authenticating for subsequent requests in that webapp

Example Code Snippets

Checker Handler Logic

public class CheckerEventHandler implements EventHandler {
    public String invoke(EventExecutionContext eec) throws EventHandlerException {
        HttpServletRequest request = eec.getRequest();
        HttpServletResponse response = eec.getResponse();
        
        // Check current webapp session first
        UserLogin userLogin = (UserLogin) request.getSession().getAttribute("userLogin");
        
        if (userLogin == null) {
            // Check for SAML NameID cookie
            String samlNameId = null;
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if ("samlNameId".equals(cookie.getName())) {
                        samlNameId = cookie.getValue();
                        break;
                    }
                }
            }
            
            // Try to fetch UserLogin from cross-webapp cache
            if (samlNameId != null) {
                userLogin = (UserLogin) SimpleCache.getCache("SAMLUserSessionCache").get(samlNameId);
                if (userLogin != null) {
                    request.getSession().setAttribute("userLogin", userLogin);
                    return "success";
                }
            }
            
            // No valid session— initiate SAML auth flow
            String originalUrl = request.getRequestURI();
            if (request.getQueryString() != null) {
                originalUrl += "?" + request.getQueryString();
            }
            String tempRelayId = UUID.randomUUID().toString();
            
            // Store original URL in cache (1-hour expiration)
            SimpleCache.getCache("SAMLRelayStateCache").put(tempRelayId, originalUrl, 3600);
            
            // Build SAML AuthnRequest with RelayState
            Saml2AuthRequest authRequest = SamlService.getInstance().generateAuthnRequest();
            authRequest.setRelayState(tempRelayId);
            String idpRedirectUrl = SamlService.getInstance().buildIdpRedirectUrl(authRequest);
            
            response.sendRedirect(idpRedirectUrl);
            return null; // Halt current request to trigger redirect
        }
        
        return "success";
    }
}

ACS Handler Logic

public class AcsEventHandler implements EventHandler {
    public String invoke(EventExecutionContext eec) throws EventHandlerException {
        HttpServletRequest request = eec.getRequest();
        HttpServletResponse response = eec.getResponse();
        
        // Process and validate SAML response
        Saml2AuthResponse authResponse = SamlService.getInstance().processAcsRequest(request);
        String samlNameId = authResponse.getNameId();
        
        // Create or retrieve UserLogin from OFBiz
        UserLogin userLogin = UserLoginService.getInstance().getOrCreateUser(samlNameId, authResponse.getAttributes());
        
        // Store UserLogin in cross-webapp cache
        SimpleCache.getCache("SAMLUserSessionCache").put(samlNameId, userLogin);
        
        // Set domain-wide cookie for SAML identity
        Cookie samlCookie = new Cookie("samlNameId", samlNameId);
        samlCookie.setDomain("ofbizwebsite.com");
        samlCookie.setPath("/");
        samlCookie.setHttpOnly(true);
        samlCookie.setSecure(true); // Enable if using HTTPS
        response.addCookie(samlCookie);
        
        // Redirect back to original request
        String tempRelayId = request.getParameter("RelayState");
        String originalUrl = (String) SimpleCache.getCache("SAMLRelayStateCache").get(tempRelayId);
        if (originalUrl == null) {
            originalUrl = "/"; // Fallback to homepage if context is lost
        }
        
        response.sendRedirect(originalUrl);
        return null;
    }
}

Key Takeaways

  • No need for multiple ACS endpoints: Your single SAMLIntegration ACS can handle all webapps by using RelayState to track original requests
  • Cross-webapp session sharing: Use OFBiz’s SimpleCache for shared user state and domain-wide cookies to identify users across webapps
  • Preserve request context: Always store the original URL before redirecting to the IdP— this ensures users land where they intended after authentication

内容的提问来源于stack exchange,提问作者King Powa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:10:28