I am trying to secure a Spring/JSF -web application with Spring Security (3.0.2), Mojarra 2.0.2, EL 2.2. Everything is working ok in the service layer, but adding even a single security annotation into a managed bean (anywhere in it, not necessarily next to something being executed) causes the whole class to fail (the methods cannot be found).
I have a managed bean like this:
My facelet calls this by:Code:@Component @Scope("request") public class LoginBean implements Serializable { private static final long serialVersionUID = 1L; @Autowired SimpleService simpleService; public void dummyMethod() { System.out.println("foo"); } public void doLogin() { System.out.println("bar"); } }
This code works ok: when user clicks the button, the doLogin() is executed succesfully in the bean.Code:<h:form id="loginForm"> <h:commandButton type="submit" id="login" value="Click me" action="#{loginBean.doLogin}"> </h:commandButton> </h:form>
Now, if I annotate the doLogin() with security declaration like this:
Clicking the button now results in:Code:@RolesAllowed({"ROLE_ADMIN"}) public void dummyMethod() { System.out.println("foo"); }
If I remove that annotation and put it for dummyMethod() instead (the method that is not even used), the result is the same.Code:javax.el.MethodNotFoundException: /login.xhtml @19,106 action="#{loginBean.doLogin}": Method not found: my.test.jsf.LoginBean@eb1882.doLogin()
However, if I inject this simple service that uses security annotations:
...and call it from the managed bean (via doLogin()), the security works ok and I get just "Access is denied" error.Code:@Service public class SimpleService { @RolesAllowed({"ROLE_ADMIN"}) public String getHelloWorld() { return "hello"; } }
What might I be missing here? Why isn't Spring Security working in the managed bean and adding an annotation anywhere there fails the whole class? Any pointers would be appreciated, thanks!
Below is my setup (find this test project also as attached zip-file):
applicationContext.xml:
applicationContext-security.xml:Code:<context:annotation-config/> <context:component-scan base-package="my.test" />
faces-config.xmlCode:<global-method-security jsr250-annotations="enabled" secured-annotations="enabled" /> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/**" access="permitAll" /> </http> <authentication-manager alias="authenticationManager"> <authentication-provider> <password-encoder hash="plaintext" /> <user-service> <user name="testadmin" password="testadmin" authorities="ROLE_ADMIN, ROLE_USER" /> <user name="testuser" password="testuser" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
web.xml:Code:<name>jsfConf</name> <application> <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> </application>
Code:<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml classpath:applicationContext-security.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>faces-servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>faces-servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <!-- For Tomcat/Jetty --> <context-param> <param-name>com.sun.faces.expressionFactory</param-name> <param-value>com.sun.el.ExpressionFactoryImpl</param-value> </context-param>


