mirror of
https://github.com/bmlong137/alfresco-keycloak.git
synced 2025-09-10 14:11:09 +00:00
Further improvements of context handling
- RequestAttributes init conflicted with some Surf / Alfresco code which partially re-initialises request context, skipping user details if request attributes contains request (ServletUtil.getRequest()) - consolidate request context handling in doFilter to remove lower-level handling in various contexts
This commit is contained in:
@@ -74,6 +74,7 @@ import org.springframework.extensions.surf.UserFactory;
|
|||||||
import org.springframework.extensions.surf.exception.ConnectorServiceException;
|
import org.springframework.extensions.surf.exception.ConnectorServiceException;
|
||||||
import org.springframework.extensions.surf.mvc.PageViewResolver;
|
import org.springframework.extensions.surf.mvc.PageViewResolver;
|
||||||
import org.springframework.extensions.surf.site.AuthenticationUtil;
|
import org.springframework.extensions.surf.site.AuthenticationUtil;
|
||||||
|
import org.springframework.extensions.surf.support.ThreadLocalRequestContext;
|
||||||
import org.springframework.extensions.surf.types.Page;
|
import org.springframework.extensions.surf.types.Page;
|
||||||
import org.springframework.extensions.surf.types.PageType;
|
import org.springframework.extensions.surf.types.PageType;
|
||||||
import org.springframework.extensions.surf.util.URLEncoder;
|
import org.springframework.extensions.surf.util.URLEncoder;
|
||||||
@@ -84,8 +85,6 @@ import org.springframework.extensions.webscripts.connector.ConnectorContext;
|
|||||||
import org.springframework.extensions.webscripts.connector.ConnectorService;
|
import org.springframework.extensions.webscripts.connector.ConnectorService;
|
||||||
import org.springframework.extensions.webscripts.connector.Response;
|
import org.springframework.extensions.webscripts.connector.Response;
|
||||||
import org.springframework.extensions.webscripts.servlet.DependencyInjectedFilter;
|
import org.springframework.extensions.webscripts.servlet.DependencyInjectedFilter;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import de.acosix.alfresco.keycloak.share.config.KeycloakAdapterConfigElement;
|
import de.acosix.alfresco.keycloak.share.config.KeycloakAdapterConfigElement;
|
||||||
import de.acosix.alfresco.keycloak.share.config.KeycloakAuthenticationConfigElement;
|
import de.acosix.alfresco.keycloak.share.config.KeycloakAuthenticationConfigElement;
|
||||||
@@ -438,6 +437,22 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
this.keycloakDeployment.getAuthServerBaseUrl());
|
this.keycloakDeployment.getAuthServerBaseUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alfresco handling of RequestContext / ServletUtil / any other context holder is so immensely broken, it isn't even funny
|
||||||
|
// Request context is indirectly required for some framework page lookups (which lack null guards) as part of our handling
|
||||||
|
// Our context is almost guaranteed to be overridden by some Surf component, which repeats the whole initialisation dance
|
||||||
|
RequestContext requestContext;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
requestContext = RequestContextUtil.initRequestContext(this.applicationContext, req, true);
|
||||||
|
}
|
||||||
|
catch (final Exception ex)
|
||||||
|
{
|
||||||
|
LOGGER.error("Error calling initRequestContext", ex);
|
||||||
|
throw new ServletException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
if (keycloakDeploymentReady && this.isLogoutRequest(req))
|
if (keycloakDeploymentReady && this.isLogoutRequest(req))
|
||||||
{
|
{
|
||||||
this.processLogout(context, req, res, chain);
|
this.processLogout(context, req, res, chain);
|
||||||
@@ -448,7 +463,7 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
|
|
||||||
if (skip)
|
if (skip)
|
||||||
{
|
{
|
||||||
if (keycloakDeploymentReady && !AuthenticationUtil.isAuthenticated(req) && this.loginFormEnhancementEnabled
|
if (!AuthenticationUtil.isAuthenticated(req) && keycloakDeploymentReady && this.loginFormEnhancementEnabled
|
||||||
&& this.isLoginPage(req))
|
&& this.isLoginPage(req))
|
||||||
{
|
{
|
||||||
this.prepareLoginFormEnhancement(context, req, res);
|
this.prepareLoginFormEnhancement(context, req, res);
|
||||||
@@ -467,6 +482,11 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
requestContext.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
{
|
{
|
||||||
LOGIN_REDIRECT_URL.remove();
|
LOGIN_REDIRECT_URL.remove();
|
||||||
}
|
}
|
||||||
@@ -1127,20 +1147,6 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
final HttpSession session = ((HttpServletRequest) request).getSession(false);
|
final HttpSession session = ((HttpServletRequest) request).getSession(false);
|
||||||
final Object keycloakAccount = session != null ? session.getAttribute(KEYCLOAK_ACCOUNT_SESSION_KEY) : null;
|
final Object keycloakAccount = session != null ? session.getAttribute(KEYCLOAK_ACCOUNT_SESSION_KEY) : null;
|
||||||
|
|
||||||
// FrameworkServlet is not involved in all requests (e.g. when proxy controller is involved)
|
|
||||||
// ensure ServletUtil.getRequest() / getSession() always works regardless (for AccessTokenAwareSlingshotAlfrescoConnector)
|
|
||||||
if (request instanceof HttpServletRequest)
|
|
||||||
{
|
|
||||||
// variant with request AND response is only available in Spring 5+
|
|
||||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes((HttpServletRequest) request));
|
|
||||||
// a bit redundant since request attributes already holds the request, but hey, that's Alfresco
|
|
||||||
// ServletUtil uses an attribute in the request attributes object separate from the main request
|
|
||||||
// see ServletUtil.VIEW_REQUEST_ATTRIBUTE_NAME
|
|
||||||
ServletUtil.setRequest((HttpServletRequest) request);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// no point in forwarding to default SSO filter if already authenticated
|
// no point in forwarding to default SSO filter if already authenticated
|
||||||
if (this.defaultSsoFilter != null && keycloakAccount == null && !this.ignoreDefaultFilter)
|
if (this.defaultSsoFilter != null && keycloakAccount == null && !this.ignoreDefaultFilter)
|
||||||
{
|
{
|
||||||
@@ -1151,12 +1157,6 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
// avoid leak - we are the top-most filter, so after we are done, no one should have interest in the holder anyway
|
|
||||||
RequestContextHolder.resetRequestAttributes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if processing of the filter must be skipped for the specified request.
|
* Checks if processing of the filter must be skipped for the specified request.
|
||||||
@@ -1362,17 +1362,8 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
protected boolean isNoAuthPage(final HttpServletRequest req) throws ServletException
|
protected boolean isNoAuthPage(final HttpServletRequest req) throws ServletException
|
||||||
{
|
{
|
||||||
final String pathInfo = req.getPathInfo();
|
final String pathInfo = req.getPathInfo();
|
||||||
RequestContext context = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
context = RequestContextUtil.initRequestContext(this.applicationContext, req, true);
|
|
||||||
}
|
|
||||||
catch (final Exception ex)
|
|
||||||
{
|
|
||||||
LOGGER.error("Error calling initRequestContext", ex);
|
|
||||||
throw new ServletException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
final RequestContext context = ThreadLocalRequestContext.getRequestContext();
|
||||||
Page page = context.getPage();
|
Page page = context.getPage();
|
||||||
if (page == null && pathInfo != null)
|
if (page == null && pathInfo != null)
|
||||||
{
|
{
|
||||||
@@ -1394,6 +1385,7 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
{
|
{
|
||||||
noAuthPage = true;
|
noAuthPage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return noAuthPage;
|
return noAuthPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1421,17 +1413,7 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check for custom login page
|
// check for custom login page
|
||||||
RequestContext context = null;
|
final RequestContext context = ThreadLocalRequestContext.getRequestContext();
|
||||||
try
|
|
||||||
{
|
|
||||||
context = RequestContextUtil.initRequestContext(this.applicationContext, req, true);
|
|
||||||
}
|
|
||||||
catch (final Exception ex)
|
|
||||||
{
|
|
||||||
LOGGER.error("Error calling initRequestContext", ex);
|
|
||||||
throw new ServletException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
Page page = context.getPage();
|
Page page = context.getPage();
|
||||||
if (page == null && pathInfo != null)
|
if (page == null && pathInfo != null)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user