0

I am currently trying to setup a project with these main technologies:

  • Java EE 7
  • EJB 3.2
  • JAX-RS (Jersey) 2.0
  • Glassfish 4
  • Spring Security 3.1.5

I saw that it is possible to write something like that

@Stateless
@Path("apath")
public class WebResource {
    @EJB
    private SomeService serviceInjected;

    @GET
    public Response doSomething() {
        return Response.ok(injectedService.doSomethingElse()).build();
    }
}

Then, this means that the SomeService Session Bean is injected by the container and once we call the path: :///apath, everything is working fine.

Now, what I try to achieve is to integrate the SpringSecurity framework in that code. So my code become this:

@Component
@Stateless
@Path("apath")
public class WebResource {
    @EJB
    private SomeService serviceInjected;

    @GET
    @PreAuthorized("hasPermission('ROLE_SOMETHING')")
    public Response doSomething() {
        return Response.ok(injectedService.doSomethingElse()).build();
    }
}

But, this does not work. Everything excepted the SpringSecurity annotations continue to work. The authorization annotations are just not taken into account.

In SpringSecurity configuration file, I have something like that:

<security:global-method-security
    access-decision-manager-ref="preVoteAccessDecisionManager"
    pre-post-annotations="enabled" />

with everything related to the filter chain and so correctly configured. For example, I have that:

<beans:bean id="securityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <beans:property name="securityMetadataSource">
        <security:filter-security-metadata-source>
            <security:intercept-url pattern="/**" access="ROLE_TEST" />
        </security:filter-security-metadata-source>
    </beans:property>
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="accessDecisionManager" ref="accessDecisionManager" />
</beans:bean>

And I see in my Glassfish 4 server logs that SpringSecurity managed the ROLE_TEST access for my authenticated user. I also see that my user authenticated has the list of roles that I expect.

I also tried to use this configuration and rely on javax.annotation.security annotations as below:

<security:global-method-security
    access-decision-manager-ref="preVoteAccessDecisionManager"
    jsr250-annotations="enabled" />

@Stateless
@Path("apath")
public class WebResource {
    @EJB
    private SomeService serviceInjected;

    @GET
    @RolesAllowed("ROLE_SOMETHING")
    public Response doSomething() {
        return Response.ok(injectedService.doSomethingElse()).build();
    }
}

This time, the annotation is working and an exception is thrown when the user is authenticated. But in this case, my user has the roles but the SecurityContext used by the container is not filled with the Principal and roles information related to the user authenticated by SpringSecurity.

Finally, my question(s). Is there a way to integrate the JAX-RS / @Stateless / SpringSecurity Authorization together? If not, is there a way to fill a SecurityContext from SrpingSecurity to allow javax.annotation.security to work like a charm?

Thanks in advance for any helps, tips, tricks or anything else that can solve my problems :D

Laurent
  • 156
  • 2
  • 11

1 Answers1

1

Spring Security's method security annotations will normally only work with Spring beans whose lifecycle is controlled by Spring. This doesn't include EJBs. However, if you wish you can use the AspectJ integration which will work for any object including EJB instances. There's a sample application in the Spring Security codebase which you can use as a reference. It might also be worth considering whether you need to use EJBs at all.

Shaun the Sheep
  • 22,353
  • 1
  • 72
  • 100