0
votes

I'm using Resteasy 3.0.11.Final with JBoss AS 5.1.0 GA. I have a defined REST web service. The whole service is secured with BASIC authentication with a custom security domain. When I use Postman to send a request (#1) with BASIC authentication for user A, JBoss AS invokes a login module for the user, and then calls a local ejb (looked up with initial context) method with caller principal A. Immidiately after I send another request (#2) with BASIC authentication for user B, in this case JBoss AS does not invoke a login module and calls a local ejb method with caller principal A again. After some time sending a request with user B yields the desired result (local ejb method call with caller principal B). I'm not sure what causes the problem, the Resteasy service configuration / session handling or the JBoss AS security domain configuration which is responsible for login modules (subject timeout? lack of logout after method being called?)? Basically I want to configure Resteasy to force a new session with a new login module invocation for the local ejb method call for every rest request.

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_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>my-app</display-name>
  <context-param>
    <param-name>resteasy.providers</param-name>
    <param-value>org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider,com.mycompany.infrastructure.ExceptionMapper</param-value>
  </context-param>
  <context-param>
    <param-name>resteasy.resources</param-name>
    <param-value>com.mycompany.resource.Resource</param-value>
  </context-param>
  <listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
  </listener>
  <servlet>
    <servlet-name>my-app-resteasy-servlet</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    <init-param>
      <param-name>javax.ws.rs.core.Application</param-name>
      <param-value>com.mycompany.application.Application</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>my-app-resteasy-servlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>my-app-resteasy-servlet</web-resource-name>
      <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>User</role-name>
    </auth-constraint>
  </security-constraint>
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>MyRealm</realm-name>
  </login-config>
  <security-role>
    <role-name>User</role-name>
  </security-role>
</web-app>

jboss-web.xml

<jboss-web>
    <context-root>/path</context-root>
    <security-domain>java:/jaas/MyRealm</security-domain>
</jboss-web>

beans.xml

<beans
       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">
</beans>

login-config.xml for MyRealm

<application-policy name="MyRealm">
     <authentication>
      <login-module code="com.mycompany.security.UsernamePasswordLoginModuleImpl"
        flag="required">
        <module-option name="password-stacking">useFirstPass</module-option>
      </login-module>
   </authentication>
</application-policy>

Resource.java

@Path("/resource")
@Stateless
public class Resource {

    @POST
    @Path("/execute")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public ResponseDTO execute(RequestDTO dto) {
        try {
            // code
        } catch (Exception exception) {
            // handle
        }
    }
}
1

1 Answers

0
votes

I found a very rough solution:

Resource.java:

@Path("/resource")
@Stateless
public class Resource {

    @POST
    @Path("/execute")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public ResponseDTO execute(RequestDTO dto, @Context HttpServletRequest request) {
        try {
            // code
        } catch (Exception exception) {
            // handle
        } finally {
            if (request != null) {
                request.getSession().invalidate();
            }
        }
    }
}

or the same result, different implementation (without repeating the same code in every method in a resource, obviously):

SessionInvalidatorFilter.java

public class SessionInvalidatorFilter implements ContainerResponseFilter {
    @Context
    private HttpServletRequest request;

    public void filter(ContainerRequestContext requestCtx, ContainerResponseContext responseCtx) throws IOException {
        if ((request != null) && (request.getSession() != null)) {
            request.getSession().invalidate();
        }
    }
}

web.xml

<context-param>
    <param-name>resteasy.providers</param-name>
    <param-value>com.mycompany.infrastructure.filter.SessionInvalidatorFilter</param-value>
</context-param>