问题
I'm using keycloak header based authentication to secure a REST API. There I want set a request header field (basically keycloak Autharization Header) before authication happes.
Another appocach for this is exlained here : How to get javax.servlet.Filter called before Keycloak Authentication
In this try I tried to call the overriden HeaderBasedKeycloakConfigResolver's
resolve method and after tempering the web.xml
. I could note that it can be called before the authentication happens. I read some request header values also but there is no setter to set the request headers to there (to org.keycloak.adapters.spi.HttpFacade.Request
).
Looking for a hint on setting a Request Header before Keycloak Auth happens in this way or another?
- Key claok version : 3.1.0.Final
HeaderBasedKeycloakConfigResolver.java
public class HeaderBasedKeycloakConfigResolver implements KeycloakConfigResolver {
@Override
public KeycloakDeployment resolve(Request request) {
String uri = request.getURI();
logger.info("resolve().uri : " + uri);
String auth_key = request.getHeader("auth_key");
logger.info("resolve().auth_key : " + auth_key);
request.setHeader("Autherization","<auth value>"); // there's no this like setter
KeycloakDeployment deployment = cache.get(applicationId);
--build deployment using the keycloak.json"
return deployment;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- more security-constraint -->
<!-- keycloak -->
<context-param>
<param-name>keycloak.config.resolver</param-name>
<param-value>package.to.class.HeaderBasedKeycloakConfigResolver</param-value>
</context-param>
<security-constraint>
<web-resource-collection>
<web-resource-name>REST endpoints</web-resource-name>
<url-pattern>/ep-name/resource-name</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>resource-name</role-name>
</auth-constraint>
</security-constraint>
<!-- more security-constraint -->
<!-- more security-constraint -->
<!-- more security-constraint -->
<login-config>
<auth-method>KEYCLOAK</auth-method>
<realm-name>realm-name</realm-name>
</login-config>
<security-role>
<role-name>role-name-for-resource-1</role-name>
<role-name>role-name-for-resource-2</role-name>
<!-- more security-role -->
<!-- more security-role -->
<!-- more security-role -->
</security-role>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/resource-path/*</url-pattern>
</servlet-mapping>
</web-app>
回答1:
As you are using security constraints in your config, you can do this:
public class CustomConstraintSecurityHandler extends ConstraintSecurityHandler{
@Override
public void handle(String pathInContext, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
try {
// change the request
super.handle(pathInContext, baseRequest, request, response);
}catch(Exception e) {
}
}
}
I have not used xml based config previously, but in Java config, I had used ConstraintSecurityHandler
somewhat like this:
ContextHandlerCollection contexts = new ContextHandlerCollection();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY );
KeycloakJettyAuthenticator kcAuthenticator = // set keycloak through JSON
CustomConstraintSecurityHandler securityHandler = new CustomConstraintSecurityHandler();
ConstraintMapping constraintMapping = new ConstraintMapping();
constraintMapping.setPathSpec("/*");
Constraint constraint = new Constraint();
constraint.setAuthenticate(true);
constraint.setRoles(new String[]{"**"});
constraintMapping.setConstraint(constraint);
securityHandler.addConstraintMapping(constraintMapping);
securityHandler.setAuthenticator(kcAuthenticator);
context.setSecurityHandler(securityHandler);
EDIT:
My answer is based on the fact that ConstraintSecurityHandler
comes before keycloak authentication handler in the debug stack trace.
来源:https://stackoverflow.com/questions/52551723/setting-request-header-in-server-before-authentication-happens-in-keycloak