如何在 Keycloak 身份验证之前调用 javax.servlet.Filter

How to get javax.servlet.Filter called before Keycloak Authentication

我们使用 resteasy 开发了 REST API。 (部署在 wildfly 10 中)

基本上这些 REST APIs 是从另一个应用程序内部调用的,端点是用 keycloak 保护的。

但是一个端点暴露给外部方(该端点也使用密钥斗篷进行保护)。

但由于外部方无法提供 Keycloak 授权代码,我们已经完成了一个实现,其中客户端使用生成的应用程序注册 auth_key,客户端将使用该 auth_key 调用端点。

然后在网络过滤器 (a javax.servlet.Filter) 中,使用 auth_key 我们获得相关的 keycloak 身份验证 Bearer 令牌。如果需要(例如:令牌过期),我们也会调用 Keycloak 服务器。收到后,我们将该授权令牌添加到 Web 过滤器中的 httpRequest 并继续进行端点应用程序。

但问题是,KeyCloak 身份验证在 Web Filter 之前被调用。 我要找的是 "how to get Web Filter called before keycloak authentication?"

编辑:

现在我正在尝试找到此处提到的方法。 Setting Request Header to Request Before Authentication Happens in Keycloak。在那里我可以在身份验证发生之前接到电话。 但是我无法在那里设置请求 Header。

web.xml

<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">
    <display-name>Restful Web Application</display-name>
    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>

    <!-- keycloak -->

    <context-param>
        <param-name>keycloak.config.resolver</param-name>
        <param-value>package.to.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>
        <init-param>
            <param-name>resteasy.servlet.mapping.prefix</param-name>
            <param-value>/ep-name</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>resteasy-servlet</servlet-name>
        <url-pattern>/ep-name/*</url-pattern>
    </servlet-mapping>

    <filter>
      <filter-name>WebFilter</filter-name>
      <filter-class>package.to.filter.WebFilter</filter-class>
   </filter>

   <filter-mapping>
      <filter-name>WebFilter</filter-name>
      <url-pattern>/desired-ep-name/*</url-pattern>
   </filter-mapping>

</web-app>

您是否尝试过更改 web.xml 中元素的顺序(例如,将过滤器定义放在 BEFORE servlet 定义之前)?

不确定它是否有效,但文档说: “过滤器在链中的顺序与过滤器映射在 Web 应用程序部署描述符中出现的顺序相同

servlet 和过滤器之间的顺序可能也是这个原理...

可能是因为 Tomcat 身份验证阀在过滤器之前启动。 检查 Authenticators.properties 文件。您可能需要将过滤器 class 包装为 Valve

我知道这已经有 2 年了,但我找到了解决这个问题的方法:将您的适配器更改为 servlet 过滤器,我的是 jboss/wildfly,然后添加到过滤器下方的 web.xml更改请求或响应。在 jboss/wildfly 的情况下,身份验证发生在阀中,因此身份验证发生在任何过滤器执行之前。完成此操作后,您可以控制 keycloak 何时开始工作并将您的过滤器放在它之前。

web.xml

<filter>
        <filter-name>Keycloak Filter</filter-name>
        <filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
</filter>
    <filter-mapping>
        <filter-name>Keycloak Filter</filter-name>
        <url-pattern>/restricted/*</url-pattern>
        <url-pattern>/restricted/</url-pattern>
</filter-mapping>

将适当版本的 keycloak-servlet-filter-adapter 添加到您的 pom,并从 web.xml.

中删除所有其他安全约束、身份验证方法等