My JEE6 webapp (mainly CDI, EJB 3.1 and JSF 2) uses Spring Security 3, but not Spring dependency injection or MVC. I implemented a Spring AuthenticationProvider to handle the login. During login, I add roles to my users depending on some custom business logic.
Now, I want to use JSR 250 annotations to secure my business logic. My business logic is implemented using stateless EJBs (version 3.1).
I include Spring's context XML file in web.xml as follows:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext-security.xml
</param-value>
</context-param>
And here is the content of the XML file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:global-method-security jsr250-annotations="enabled"/>
<security:http auto-config="false">
<security:intercept-url pattern="/pages/**" access="ROLE_USER"/>
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<security:form-login login-page="/login.jsf"/>
<security:anonymous/>
<security:custom-filter ref="logoutFilter" position="LOGOUT_FILTER"/>
</security:http>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg index="0" value="/login.jsf"/>
<constructor-arg index="1">
<list>
<bean id="customLogoutHandler" class="com.example.client.security.CustomLogoutHandler"/>
<bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout.jsf"/>
</bean>
<security:authentication-manager>
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
<bean id="customAuthenticationProvider"
class="com.example.client.security.CustomAuthenticationProvider"/>
</beans>
In my classes, I use class annotations (type level) to say all methods should be only accessible to users with a certain role:
@Model
@RolesAllowed("ROLE_GROUP")
public class UserListAction {
However, also users with only the role ROLE_USER have access to any function of this class. I verified that the users don't have the wrong roles while debugging with the following code:
Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
As expected, the authorities collection doesn't contain the ROLE_GROUP authority.
It seems my annotations are completely ignored, but why? I also tried Spring's pre-post annotations, but they also seem to have no effect.