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

13

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

基本上这些REST API是从另一个应用程序内部调用的,并且端点受到Keycloak的保护。

但是一个端点向外部公开(该端点也受到Keycloak的保护)。

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

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

但问题是,“KeyCloak身份验证是在Web过滤器之前调用的”。 我正在寻找“如何在keycloak身份验证之前调用Web过滤器?”

编辑:

现在我正在尝试按照此处所述的方式查找方法。那里我可以在身份验证发生之前进行调用。 但我无法在那里设置请求标题。

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>

在此输入图片描述


你找到解决问题的方法了吗? - tryingToLearn
我仍然没有找到答案。我用另一种方式解决了它。但现在我正在尝试按照这里提到的方法找到一种方法。https://stackoverflow.com/questions/52551723/setting-request-header-to-request-before-authentication-happens-in-keycloak 在那里,我可以在身份验证发生之前获取调用。但是我无法设置请求头。 - ironwood
一个不错的解决方案请参见 https://arjan-tijms.omnifaces.org/2012/12/bridging-undertows-authentication.html,仅适用于 Undertow,但它很好地说明了这个想法。 - leonardkraemer
3个回答

6
你尝试过更改web.xml文件中元素的顺序(例如将过滤器定义放在servlet定义之前)吗?虽然不确定是否有效,但文档中说:“过滤器链中过滤器的顺序与Web应用程序部署描述符中出现的过滤器映射的顺序相同”。这个原则也可能适用于servlet和过滤器之间的顺序...

谢谢@TacheDeChoco的回答。但是它不起作用。 - ironwood
接受这个建议,尽管它并不是我问题的正确解决方案,但仍然有帮助。 - ironwood
@namalfernandolk,你找到解决问题的方法了吗?在上面的评论中,你提到这个解决方案没有起作用。 - tryingToLearn
1
@tryingToLearn:是的,我仍然没有找到答案。我用另一种方法解决了它。但现在我正在尝试按照这里提到的方式找到一种方法。https://stackoverflow.com/questions/52551723/setting-request-header-to-request-before-authentication-happens-in-keycloak。在那里,我可以在身份验证发生之前获得调用。但我无法设置请求头。 - ironwood

4
可能是因为Tomcat身份验证阀在过滤器之前启动了。 请检查Authenticators.properties文件。您可能需要将您的过滤器类包装成阀门。

感谢Adrain0的回答。我已经检查过了。 - ironwood
@namalfernandolk,你找到解决方案了吗? - Adrian0
1
还没有!但我用另一种方法解决了。我发现我一定会在这里更新,这将拯救其他人的生命。 - ironwood
@namalfernandolk,你采取了哪种其他的方法呢? - tryingToLearn
@tryingToLearn:它基于与另一个API的重定向。 - ironwood
显示剩余2条评论

1
我知道这篇文章已经有两年了,但我找到了一个解决方案:将适配器更改为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中删除所有其他安全约束、auth-method等。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接