0

I'm using Spring to handle security in my JSF application. I have a login page at /login and I've configured Spring like this:

<http authentication-manager-ref="authenticationManager">
    <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <intercept-url pattern="/admin" access="ROLE_ADMIN" />
    <intercept-url pattern="/javax.faces.resource/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_USER" />
    <form-login login-page="/login" authentication-failure-url="/login" />
    <logout logout-url="/logout" />
</http>

I want the admin page at /admin to be available only for users with the ROLE_ADMIN role. Users with ROLE_ADMIN or ROLE_USER may access pages starting from the application root.

When I login with a user having either role I see the page you should see after login. However, whatever my next action may be I get redirected to /login like I'm not logged in. Can someone please explain this as I'm trying to get this thing to work for a day now. I've been reading the Spring 3.1.x documentation but it doesn't give me a clue about how to solve the problem. I'm running Spring 3.1.1.Release by the way.

Extra bonus info: the page you should see after login has an element that should only render if the user had ROLE_ADIN. I can see that element after login. The problems began when I implemented PrettyFaces. I've searched the web for common problems and only came up with that the PrettyFaces filter should appear after the Spring security filter. This is the case so it should work right?

UPDATE: I've updated my config to use expressions. However the problem still exists.

<http authentication-manager-ref="authenticationManager" use-expressions="true">
    <intercept-url pattern="/login" access="permitAll" />
    <intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/javax.faces.resource/**" access="permitAll" />
    <intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" />
    <form-login login-page="/login" authentication-failure-url="/login" />
    <logout logout-url="/logout" />
</http>

Output in Firebug's console just after login (the page tries an AJAX call):

Firebug console log

siebz0r
  • 18,867
  • 14
  • 64
  • 107
  • [This](http://stackoverflow.com/questions/8326587/determine-target-url-based-on-roles-in-spring-security-3-1) question may be related. But in the example you need Spring MVC, I believe that if you are using Spring Security you still have access to a request wrapped in a SecurityContextHolderAwareRequestWrapper. – ElderMael Sep 13 '12 at 15:36
  • To clarify: you have two types of users: first type has **only** `ROLE_USER` and second has **only** `ROLE_ADMIN` (I mean XOR). Is this true? – Grzegorz Rożniecki Sep 13 '12 at 15:38
  • @Xaerxess A user can have one role or both. The user I'm testing with only has `ROLE_ADMIN`. – siebz0r Sep 13 '12 at 15:57
  • @mael I don't think that's related. The redirect after login works as expected. Any call after that gets redirected to `/login`. – siebz0r Sep 13 '12 at 16:00
  • How do you handle "/" mapping? Isn't it mapped to login? Can you show the controller code? – Grzegorz Rożniecki Sep 14 '12 at 21:23
  • @Xaerxess The "/" is handled by PrettyFaces. Spring checks the URL first. If the user isn't logged in it is redirected to "/login". – siebz0r Sep 14 '12 at 21:27
  • Hmm, that's a pity you didn't managed to run debug, because I can't say more without some logs... – Grzegorz Rożniecki Sep 14 '12 at 21:31

1 Answers1

1

First, always debug Spring Security when having problems (add log4j.logger.org.springframework.security=DEBUG).

Second, I think that you wanted hasAnyRole:

<intercept-url pattern="/**" access="hasAnyRole(ROLE_ADMIN,ROLE_USER)" />

plus add use-expressions="true" to http:

<http authentication-manager-ref="authenticationManager" use-expressions="true">

to allow ROLE_ADMIN xor ROLE_USER users to access page. In your current config user must have both roles to access /**.

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112
  • I've updated my config accordingly, see my updates answer. The problem still exists. – siebz0r Sep 13 '12 at 17:08
  • Can you turn Spring Security debug on and post logs in question, too? – Grzegorz Rożniecki Sep 13 '12 at 17:12
  • I can't get the logging to work. I've tried this before and spent a couple of hours doing so. Now I've spent another couple of worthless hours trying. When I finally get it to work I'll post back, any chance you know a good guide that works for 3.1.1? – siebz0r Sep 13 '12 at 19:21
  • [Petclinic](http://static.springsource.org/spring-security/site/petclinic-tutorial.html) is for Spring Security 3.0, but I you don't know Spring Security at all it should be sufficient. If you want to catch up with 3.1, [read reference manual](http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#new-3.1). – Grzegorz Rożniecki Sep 13 '12 at 19:22
  • About logging: did you added `src/main/resources/log4j.properties` file like [in example](http://www.mkyong.com/logging/log4j-log4j-properties-examples/) + Spring Security line? BTW There's easier method in 3.1: just add `` in your `security-context.xml` - it's a bit less verbose, but we'll see. – Grzegorz Rożniecki Sep 13 '12 at 19:23
  • Earlier today I've tried ``, this didn't supply useful information. I'm reading the documentation and using it's examples. I tried the Petclinic already (just now), didn't show any logging. – siebz0r Sep 13 '12 at 19:36
  • Just read through [this documentation](http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/overview.html#overview-logging), excluded commons-logging and configured log4j as described. Nothing.. not a line of info. – siebz0r Sep 13 '12 at 19:38
  • Don't exclude commons-logging unless you want to use slf4j. Normally, [simple log4j configuration](http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/overview.html#overview-logging-log4j) will be sufficient as it'll _work with the default JCL dependency (commons-logging)_. Doing **exactly** what's described in 1.3.2.3 should enable console debugging. – Grzegorz Rożniecki Sep 13 '12 at 20:22
  • I finally solved the problem. The PrettyFaces filter had to be placed **before** the Spring security filter in web.xml. The Spring security filer doesn't get a chance to store the authentication token in the session. Logging didn't work because I'm running a JBoss server and JBoss is running log4j. To get it working I needed to exclude the log4j library using a JBoss deployment descriptor. Thanks for your support ;-) – siebz0r Sep 18 '12 at 09:20