1

I have a simple web app example. Some unsecured pages and some secured pages.

Login is via Spring Security and CAS. Application is mostly working OK - users get directed to CAS login page when requesting a secured resource, login works, and user gets redirected back to the secure page they requested. User will have various authentication properties - available to be checked with Spring Security taglib : http://www.springframework.org/security/tags - eg:

Authentication class : 
    class   org.springframework.security.web.
    authentication.preauth.PreAuthenticatedAuthenticationToken

Authentication authorities : [ROLE_ADMIN]

Authentication name : admin-user

Authentication authenticated : true

Authentication principal : 
    org.springframework.security.core.userdetails.User@bf0d4bda:
    Username: admin-user; 
    Password: [PROTECTED]; 
    Enabled: true; 
    AccountNonExpired: true;   
    credentialsNonExpired: true; 
    AccountNonLocked: true; 
    Granted Authorities: ROLE_ADMIN

However, once that logged-in user visits a non-secured page, then they appear to be seen as having none of these credentials. Instead, they are see as

Authentication class : class 
    org.springframework.security.authentication.AnonymousAuthenticationToken

Authentication authorities : [ROLE_ANONYMOUS]

Authentication name : anonymousUser

Authentication authenticated : true

Authentication principal : anonymousUser

So, this makes it impossible to use the security taglib to show or hide page items on the unsecured pages based on whether or not the user is logged in - eg, can't show a logout button if the user is already logged in:

<sec:authorize access="isAuthenticated()" >
    <a href='<c:url value="/j_spring_security_logout" />'>logout</a>
</sec:authorize>

or show login button if not logged in:

<sec:authorize access="not isAuthenticated()" >
    <a href='<c:url value="/secure/home" />'>login</a>
</sec:authorize>

Logged in user always shows as not authenticated in these pages even when logged in. So always sees the login button, and never the logout. When going back to a secured page, there is no problem. This is not fatal to my app - but the same principle makes it impossible for me to customise the non-secured pages with content only appropriate to logged in users (menus, messages, etc).

Is this normal behaviour with Spring Security + CAS? Or is there a way to make it work as you would expect? Perhaps I have misconfigured the filter chains?

One more thing - I have exeprimented with looking at SPRING_SECURITY_CONTEXT in the session. At first I thought this would work - this gets popluated with Granted Authorities = ROLE_ADMIN on the unsecured pages. So, I thought I could use that to detect if a user was logged in and had the correct authority. However, SPRING_SECURITY_CONTEXT does not get popluated on the very first secured page that gets loaded on the return from CAS - only on subsequent page loads.

Steve
  • 779
  • 2
  • 6
  • 18
  • please see http://stackoverflow.com/questions/7391735/difference-between-access-permitall-and-filters-none – Ritesh Nov 26 '11 at 03:16
  • How does that help? Pet Clinic does not use CAS. – Steve Nov 28 '11 at 13:27
  • Looks like I had misconfigured the configuration. Missing SecurityContextPersistenceFilter from the filter chain for the unsecured pages. Adding this seems to work and maintain the logged in user role when back in the non-secured pages. – Steve Nov 28 '11 at 13:55
  • I was suspecting that you had turned off the filters on non-secured requests. Missing SecurityContextPersistenceFilter from the filter chain for the unsecured pages would have same effect. good that you resolved the issue. – Ritesh Nov 28 '11 at 20:39

1 Answers1

0

You have to tell to the Spring session manager that there is actually a session for the user and that Spring has to maintain it.

<http use-expressions="true"
    auto-config="true"
    lowercase-comparisons="true"
    disable-url-rewriting="true"
    access-denied-page="/accessDenied.jsf"
    entry-point-ref="casAuthenticationFilterEntryPoint">
    [..]
    <custom-filter ref="concurrencyFilter" position="CONCURRENT_SESSION_FILTER" />
    <custom-filter ref="casAuthenticationFilter" position="CAS_FILTER" />

    <logout invalidate-session="true" 
        logout-success-url="${cas.url}/logout?service=${local.url}/workspace/" />
</http>

That's a part of the security filter chain, that we implemented, the important is the concurrencyFilter that is defined below and the casAuthenticationFilter

<beans:bean id="casAuthenticationFilter"
    class="org.springframework.security.cas.web.CasAuthenticationFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
    <beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
    <beans:property name="sessionAuthenticationStrategy" ref="sas" />
</beans:bean>

<beans:bean id="sas"
    class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
    <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
    <beans:property name="migrateSessionAttributes" value="true" />
    <beans:property name="exceptionIfMaximumExceeded" value="true" />
    <beans:property name="alwaysCreateSession" value="true" />
    <beans:property name="maximumSessions" value="20" />
</beans:bean>

<beans:bean id="sessionRegistry"
    class="org.springframework.security.core.session.SessionRegistryImpl" />

<beans:bean id="concurrencyFilter"
    class="org.springframework.security.web.session.ConcurrentSessionFilter">
    <beans:property name="sessionRegistry" ref="sessionRegistry" />
    <beans:property name="expiredUrl" value="/sessionExpired.jsf" />
</beans:bean>

I hope that helps, and is complete. I've to leave now, but if you need more just ask

Hons
  • 3,804
  • 3
  • 32
  • 50