Authentication with virtual hosts goes to a blank page with Weblogic

Description

STEPS TO REPRODUCE
------------------ 1.- Set up a Liferay 6.1 EE GA2 over Weblogic 10.3.5
2.- Change the cirtual host for the portal in Control panel > Portal settings > General > Virtual host
3.- Log in to the portal using the virtual host URL

OBSERVED BEHAVIOUR
------------------ The authentication flow stops at a blank page with an URL like http://virtualhost:7001/c

The usual authentication flow is (see authentication-flow.png)
1.- HTTP POST request with login credentials
2.- HTTP 302 redirect to '/c'
3.- HTTP 302 redirect usually to the home page.

If the virtual host is the default one (localhost), it is working fine.
If it is changed, the following flow takes place:

1.- HTTP POST with login credentials

2.- HTTP 302 redirect to '/c'

2.1.- Cookies are set inside SERVLET processing.

Daemon Thread [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 83 in CookieUtil))
CookieUtil._getCookieMap(HttpServletRequest) line: 83
CookieUtil.get(HttpServletRequest, String, boolean) line: 39
CookieKeys.getCookie(HttpServletRequest, String, boolean) line: 103
CookieKeys.validateSupportCookie(HttpServletRequest) line: 212
ServicePreAction.initThemeDisplay(HttpServletRequest, HttpServletResponse) line: 387
ServicePreAction.servicePre(HttpServletRequest, HttpServletResponse) line: 1939
ServicePreAction.run(HttpServletRequest, HttpServletResponse) line: 1292
EventsProcessorImpl(EventsProcessorImpl).processEvent(Object, String[], HttpServletRequest, HttpServletResponse, HttpSession) line: 81
EventsProcessorImpl(EventsProcessorImpl).process(String, String[], String[], HttpServletRequest, HttpServletResponse, HttpSession) line: 58
EventsProcessorImpl.process(String, String[], String[], HttpServletRequest, HttpServletResponse, HttpSession) line: not available
EventsProcessorUtil.process(String, String[], HttpServletRequest, HttpServletResponse) line: 40
MainServlet.processServicePre(HttpServletRequest, HttpServletResponse, long) line: 1204
MainServlet.service(HttpServletRequest, HttpServletResponse) line: 501
MainServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 820

Request here is of type: com.liferay.portal.kernel.servlet.ProtectedServletRequest@14b5335a

2.2.- Redirection to lastPath and cookie read

Daemon Thread [[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended)
CookieUtil._getCookieMap(HttpServletRequest) line: 60
CookieUtil.get(HttpServletRequest, String, boolean) line: 39
CookieKeys.getCookie(HttpServletRequest, String, boolean) line: 103
CookieKeys.hasSessionId(HttpServletRequest) line: 185
AbsoluteRedirectsResponse.sendRedirect(String) line: 52
StringServletResponse(HttpServletResponseWrapper).sendRedirect(String) line: 136
StringServletResponse(HeaderCacheServletResponse).sendRedirect(String) line: 188
PortalRequestProcessor.process(HttpServletRequest, HttpServletResponse) line: 171
MainServlet(ActionServlet).process(HttpServletRequest, HttpServletResponse) line: 1196
MainServlet(ActionServlet).doGet(HttpServletRequest, HttpServletResponse) line: 414
MainServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 707

Request here is weblogic.servlet.internal.ServletRequestImpl and hence a ClassCastException

18:17:14,196 ERROR [[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)'][StripFilter:81] java.lang.ClassCastException: com.liferay.portal.kernel.servlet.NonSerializableObjectHandler
java.lang.ClassCastException: com.liferay.portal.kernel.servlet.NonSerializableObjectHandler
at com.liferay.util.CookieUtil._getCookieMap(CookieUtil.java:59)
at com.liferay.util.CookieUtil.get(CookieUtil.java:39)
at com.liferay.portal.util.CookieKeys.getCookie(CookieKeys.java:103)
at com.liferay.portal.util.CookieKeys.hasSessionId(CookieKeys.java:185)
at com.liferay.portal.servlet.filters.absoluteredirects.AbsoluteRedirectsResponse.sendRedirect(AbsoluteRedirectsResponse.java:52)
at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:136)
at com.liferay.portal.kernel.servlet.HeaderCacheServletResponse.sendRedirect(HeaderCacheServletResponse.java:188)
at com.liferay.portal.struts.PortalRequestProcessor.process(PortalRequestProcessor.java:171)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at com.liferay.portal.servlet.MainServlet.callParentService(MainServlet.java:560)
at com.liferay.portal.servlet.MainServlet.service(MainServlet.java:537)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:821)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:300)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:27)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
at com.liferay.portal.servlet.filters.strip.StripFilter.processFilter(StripFilter.java:338)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
at com.liferay.portal.servlet.filters.secure.SecureFilter.processFilter(SecureFilter.java:294)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:74)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57)
at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:524)
at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:253)
at com.liferay.portal.servlet.I18nServlet.service(I18nServlet.java:102)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:821)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:300)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:27)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
at com.liferay.portal.servlet.filters.sso.ntlm.NtlmPostFilter.processFilter(NtlmPostFilter.java:84)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:163)
at com.liferay.portal.sharepoint.SharepointFilter.processFilter(SharepointFilter.java:83)
at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:57)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:187)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:95)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:738)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:206)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:108)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:167)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:95)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:167)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:95)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:116)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:187)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:95)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:74)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3715)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3681)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)

3.- Blank page

The difference (see diff-flow.png) with the authentication flow that works is in step 2.1. Here, cookies are set inside servlet processing where the request object is wrapped. Then, cookies are read inside filter processing and there the request is not wrapped.

The flow that succeeds sets and reads cookies inside filter processing:

1.- HTTP POST with login credentials

2.- HTTP 302 redirect to '/c'

2.1.- Cookies are set inside FILTER processing.

Daemon Thread [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 83 in CookieUtil))
CookieUtil._getCookieMap(HttpServletRequest) line: 83
CookieUtil.get(HttpServletRequest, String, boolean) line: 39
CookieKeys.getCookie(HttpServletRequest, String, boolean) line: 103
PortalInstances._getCompanyId(HttpServletRequest) line: 168
PortalInstances.getCompanyId(HttpServletRequest) line: 70
AbsoluteRedirectsFilter.doFilterTry(HttpServletRequest, HttpServletResponse) line: 59
InvokerFilterChain.processDirectCallFilter(Filter, HttpServletRequest, HttpServletResponse) line: 185
InvokerFilterChain.doFilter(ServletRequest, ServletResponse) line: 95
InvokerFilterChain.doFilter(ServletRequest, ServletResponse) line: 116
InvokerFilterChain.doFilter(ServletRequest, ServletResponse) line: 116
InvokerFilterChain.doFilter(ServletRequest, ServletResponse) line: 116
InvokerFilterChain.doFilter(ServletRequest, ServletResponse) line: 116
UrlRewriteFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 738
InvokerFilterChain.processDoFilter(Filter, ServletRequest, ServletResponse) line: 206
InvokerFilterChain.doFilter(ServletRequest, ServletResponse) line: 108

Request here is of type: weblogic.servlet.internal.ServletRequestImpl

2.2.- Redirection to lastPath and cookie read

Daemon Thread [[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended)
CookieUtil._getCookieMap(HttpServletRequest) line: 60
CookieUtil.get(HttpServletRequest, String, boolean) line: 39
CookieKeys.getCookie(HttpServletRequest, String, boolean) line: 103
CookieKeys.hasSessionId(HttpServletRequest) line: 185
AbsoluteRedirectsResponse.sendRedirect(String) line: 52
StringServletResponse(HttpServletResponseWrapper).sendRedirect(String) line: 136
StringServletResponse(HeaderCacheServletResponse).sendRedirect(String) line: 188
PortalRequestProcessor.process(HttpServletRequest, HttpServletResponse) line: 171
MainServlet(ActionServlet).process(HttpServletRequest, HttpServletResponse) line: 1196
MainServlet(ActionServlet).doGet(HttpServletRequest, HttpServletResponse) line: 414
MainServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 707

Request here is weblogic.servlet.internal.ServletRequestImpl

3.- 302 redirect to lastPath 'http://sergio.com:7001'

EXPECTED BEHAVIOR
-----------------
The authentication flow should finish.

Environment

Liferay 6.1 EE GA2 + Weblogic 10.3.5

Attachments

2

Activity

Show:

Pani GuiJanuary 22, 2013 at 9:53 PM

PASSED Manual Testing following the steps in the description.

Reproduced on:
Weblogic 10 + MySQL 5. Portal 6.1.20 EE GA2.

The page is blank when sign in with virtual host on Weblogic.

Fixed on:
Weblogic 10 + MySQL 5. Portal 6.1.x EE GIT ID: febe1fa217a5859f770442405eeb455a6c72bf3a.
Weblogic 10 + MySQL 5. Portal 6.2.x GIT ID: 838cef246e57e86ae29e9d7d4e145c22c9ffb53a.

The page will not be blank.

Igor SpasicJanuary 10, 2013 at 8:16 AM

When I removed changes from RestrictPortletServletRequest, problem appears again (on trunk). Here is how to recreate: login and click on 'Add', then on 'More...'. This will give the following exception:

Here is what is going on, in this test case.

Everythong is fine until PortalRequestProcessor, line #174:

This will call structs and then RenderPortletAction, line #96:

what brings us to PortalContainerImpl, line #769:

So we are including portlet_render.jsp and therefore, InvokeFilter is executed again. Because NonSerializableObjectRequestWrapper is the first one, we can not use 'instance of' to check if it is already applied. Therefore, new NonSerializableObjectRequestWrapper will wrap RestrictPortletServletRequest and that is the core reason of failure.

When I fix this and add detection of wrapped request differently (not using instaceof) then everything works.

Thanks Shuyang Zhou for being persistent on fixing this in correct way ))

Igor SpasicJanuary 10, 2013 at 4:42 AM
Edited

After discussion with Shuyang Zhou, we agreed that RestrictPortletServletRequest should not be aware of NonSerializable wrapper. Therefore, I rollbacked just the changes in RestrictPortletServletRequest and tried running portal both on trunk and 6.1.x.

Igor SpasicJanuary 9, 2013 at 4:16 PM

This is now proper fix. It works for 6.2.x and 6.1.x.
Therefore, it has to be backported (6.1.x on weblogic wont even start)

Igor SpasicJanuary 9, 2013 at 2:33 PM

I need to work more on this, as i can not reproduce serialization error in the debug mode.

Fixed
Pinned fields
Click on the next to a field label to start pinning.

Details

Assignee

Reporter

Branch Version/s

6.1.x

Backported to Branch

Committed

Git Pull Request

Components

Priority

Zendesk Support

Created December 21, 2012 at 12:38 AM
Updated June 25, 2023 at 10:27 PM
Resolved January 10, 2013 at 8:59 AM