views:

1712

answers:

2

Spring version: 2.5.6 SEC01
Spring Security version: 3.0.0 RC1

I'm attempting to integrate Spring Security with a Spring MVC application. The security part is largely based on the example applcation that ships with Spring Security. I've defined some pages that require a specific role to access them and as expected, when accessing them without being logged in the login page appears (I have defined my own login page). The problem is that even when I enter the correct username and password, I get thrown back to the login page. I'm not entirely certain if this is a Spring Security issue or a Spring MVC issue, but lets try the former first. I have the logging for the requests so maybe somebody more familiar with them will be able to spot something.

There is quite a lot of logging (more than is permitted in one post itseems) so I've just included the most interesting bit. From what I can understand, the login of user 'rod' is successful and everything seems to be ok up until the line at time 14:30:28,222 where I see Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser;... and from then on the user is deemed to be anonymous again.

Here is the debugging after entering the correct username and password that results in being thrown back to the login page:

14:30:28,192 DEBUG FilterChainProxy:176 - Converted URL to lowercase, from: '/j_spring_security_check'; to: '/j_spring_security_check'
14:30:28,192 DEBUG FilterChainProxy:183 - Candidate is: '/j_spring_security_check'; pattern is /**; matched=true
14:30:28,192 DEBUG FilterChainProxy:351 - /j_spring_security_check at position 1 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.channel.ChannelProcessingFilter@2a4e37fb'
14:30:28,193 DEBUG DefaultFilterInvocationSecurityMetadataSource:177 - Converted URL to lowercase, from: '/j_spring_security_check'; to: '/j_spring_security_check'
14:30:28,193 DEBUG DefaultFilterInvocationSecurityMetadataSource:204 - Candidate is: '/j_spring_security_check'; pattern is /login.htm; matched=false
14:30:28,193 DEBUG FilterChainProxy:351 - /j_spring_security_check at position 2 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.session.ConcurrentSessionFilter@753d556f'
14:30:28,193 DEBUG FilterChainProxy:351 - /j_spring_security_check at position 3 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@db4268b'
14:30:28,194 DEBUG HttpSessionSecurityContextRepository:145 - HttpSession returned null object for SPRING_SECURITY_CONTEXT
14:30:28,194 DEBUG HttpSessionSecurityContextRepository:91 - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@2e4e76b4. A new one will be created.
14:30:28,194 DEBUG FilterChainProxy:351 - /j_spring_security_check at position 4 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@21533b2c'
14:30:28,194 DEBUG FilterChainProxy:351 - /j_spring_security_check at position 5 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@5f51d6cb'
14:30:28,194 DEBUG UsernamePasswordAuthenticationFilter:194 - Request is to process authentication
14:30:28,197 DEBUG ProviderManager:118 - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
14:30:28,203 DEBUG ConcurrentSessionControlStrategy:82 - Invalidating session with Id 'F281373E7B726C52448CDBB845DC0FA0' and migrating attributes.
14:30:28,204 DEBUG ConcurrentSessionControlStrategy:92 - Started new session: 24853B27E3FF94289CBB879FEA7EE27A
14:30:28,204 DEBUG SessionRegistryImpl:115 - Registering session 24853B27E3FF94289CBB879FEA7EE27A, for principal org.springframework.security.core.userdetails.User@2117c700: Username: rod; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR, ROLE_TELLER, ROLE_USER
14:30:28,205 DEBUG UsernamePasswordAuthenticationFilter:290 - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@86589b6c: Principal: org.springframework.security.core.userdetails.User@2117c700: Username: rod; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR, ROLE_TELLER, ROLE_USER; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffe9938: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: F281373E7B726C52448CDBB845DC0FA0; Granted Authorities: ROLE_SUPERVISOR, ROLE_TELLER, ROLE_USER
14:30:28,205 DEBUG SavedRequestAwareAuthenticationSuccessHandler:78 - Redirecting to DefaultSavedRequest Url: http://localhost:8080/vicinity/member/member_home.htm
14:30:28,206 DEBUG DefaultRedirectStrategy:55 - Redirecting to 'http://localhost:8080/vicinity/member/member_home.htm'
14:30:28,206 DEBUG HttpSessionSecurityContextRepository:332 - SecurityContext stored to HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@86589b6c: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@86589b6c: Principal: org.springframework.security.core.userdetails.User@2117c700: Username: rod; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR, ROLE_TELLER, ROLE_USER; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffe9938: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: F281373E7B726C52448CDBB845DC0FA0; Granted Authorities: ROLE_SUPERVISOR, ROLE_TELLER, ROLE_USER'
14:30:28,207 DEBUG SecurityContextPersistenceFilter:90 - SecurityContextHolder now cleared, as request processing completed
14:30:28,217 DEBUG FilterChainProxy:176 - Converted URL to lowercase, from: '/member/member_home.htm'; to: '/member/member_home.htm'
14:30:28,217 DEBUG FilterChainProxy:183 - Candidate is: '/member/member_home.htm'; pattern is /**; matched=true
14:30:28,217 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 1 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.channel.ChannelProcessingFilter@2a4e37fb'
14:30:28,217 DEBUG DefaultFilterInvocationSecurityMetadataSource:177 - Converted URL to lowercase, from: '/member/member_home.htm'; to: '/member/member_home.htm'
14:30:28,218 DEBUG DefaultFilterInvocationSecurityMetadataSource:204 - Candidate is: '/member/member_home.htm'; pattern is /login.htm; matched=false
14:30:28,218 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 2 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.session.ConcurrentSessionFilter@753d556f'
14:30:28,218 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 3 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@db4268b'
14:30:28,218 DEBUG HttpSessionSecurityContextRepository:133 - No HttpSession currently exists
14:30:28,218 DEBUG HttpSessionSecurityContextRepository:91 - No SecurityContext was available from the HttpSession: null. A new one will be created.
14:30:28,219 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 4 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@21533b2c'
14:30:28,219 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 5 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@5f51d6cb'
14:30:28,219 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 6 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.www.BasicAuthenticationFilter@75ecda50'
14:30:28,219 DEBUG BasicAuthenticationFilter:118 - Authorization header: null
14:30:28,219 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 7 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.savedrequest.RequestCacheAwareFilter@10f0f6ac'
14:30:28,220 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 8 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3bd29ee4'
14:30:28,220 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 9 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.AnonymousAuthenticationFilter@bda96b'
14:30:28,220 DEBUG AnonymousAuthenticationFilter:98 - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
14:30:28,220 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 10 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.session.SessionManagementFilter@23bdb02e'
14:30:28,221 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 11 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.ExceptionTranslationFilter@7a79ae56'
14:30:28,221 DEBUG FilterChainProxy:351 - /member/member_home.htm at position 12 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.intercept.FilterSecurityInterceptor@4aa4ceeb'
14:30:28,221 DEBUG DefaultFilterInvocationSecurityMetadataSource:177 - Converted URL to lowercase, from: '/member/member_home.htm'; to: '/member/member_home.htm'
14:30:28,222 DEBUG DefaultFilterInvocationSecurityMetadataSource:204 - Candidate is: '/member/member_home.htm'; pattern is /member/**; matched=true
14:30:28,222 DEBUG FilterSecurityInterceptor:192 - Secure object: FilterInvocation: URL: /member/member_home.htm; Attributes: [ROLE_TELLER]
14:30:28,222 DEBUG FilterSecurityInterceptor:293 - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
14:30:28,222 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.RoleVoter@a0ccc96, returned: -1
14:30:28,223 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.AuthenticatedVoter@4e4b9101, returned: 0
14:30:28,223 DEBUG ExceptionTranslationFilter:154 - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:71)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:204)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
    SNIP...
14:30:28,224 DEBUG HttpSessionRequestCache:39 - DefaultSavedRequest added to Session: DefaultSavedRequest[http://localhost:8080/vicinity/member/member_home.htm]
14:30:28,225 DEBUG ExceptionTranslationFilter:178 - Calling Authentication entry point.
14:30:28,225 DEBUG DefaultRedirectStrategy:55 - Redirecting to 'http://localhost:8080/vicinity/login.htm'
14:30:28,225 DEBUG SecurityContextPersistenceFilter:90 - SecurityContextHolder now cleared, as request processing completed
14:30:28,227 DEBUG FilterChainProxy:176 - Converted URL to lowercase, from: '/login.htm'; to: '/login.htm'
14:30:28,228 DEBUG FilterChainProxy:183 - Candidate is: '/login.htm'; pattern is /**; matched=true
14:30:28,228 DEBUG FilterChainProxy:351 - /login.htm at position 1 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.channel.ChannelProcessingFilter@2a4e37fb'
14:30:28,228 DEBUG DefaultFilterInvocationSecurityMetadataSource:177 - Converted URL to lowercase, from: '/login.htm'; to: '/login.htm'
14:30:28,228 DEBUG DefaultFilterInvocationSecurityMetadataSource:204 - Candidate is: '/login.htm'; pattern is /login.htm; matched=true
14:30:28,229 DEBUG ChannelProcessingFilter:100 - Request: FilterInvocation: URL: /login.htm; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
14:30:28,229 DEBUG RetryWithHttpsEntryPoint:65 - Redirecting to: https://localhost:8443/vicinity/login.htm
14:30:28,231 DEBUG FilterChainProxy:176 - Converted URL to lowercase, from: '/login.htm'; to: '/login.htm'
14:30:28,231 DEBUG FilterChainProxy:183 - Candidate is: '/login.htm'; pattern is /**; matched=true
14:30:28,231 DEBUG FilterChainProxy:351 - /login.htm at position 1 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.channel.ChannelProcessingFilter@2a4e37fb'
14:30:28,232 DEBUG DefaultFilterInvocationSecurityMetadataSource:177 - Converted URL to lowercase, from: '/login.htm'; to: '/login.htm'
14:30:28,232 DEBUG DefaultFilterInvocationSecurityMetadataSource:204 - Candidate is: '/login.htm'; pattern is /login.htm; matched=true
14:30:28,232 DEBUG ChannelProcessingFilter:100 - Request: FilterInvocation: URL: /login.htm; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
14:30:28,232 DEBUG FilterChainProxy:351 - /login.htm at position 2 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.session.ConcurrentSessionFilter@753d556f'
14:30:28,232 DEBUG FilterChainProxy:351 - /login.htm at position 3 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@db4268b'
14:30:28,233 DEBUG HttpSessionSecurityContextRepository:145 - HttpSession returned null object for SPRING_SECURITY_CONTEXT
14:30:28,233 DEBUG HttpSessionSecurityContextRepository:91 - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@384e9bea. A new one will be created.
14:30:28,233 DEBUG FilterChainProxy:351 - /login.htm at position 4 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@21533b2c'
14:30:28,233 DEBUG FilterChainProxy:351 - /login.htm at position 5 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@5f51d6cb'
14:30:28,234 DEBUG FilterChainProxy:351 - /login.htm at position 6 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.www.BasicAuthenticationFilter@75ecda50'
14:30:28,234 DEBUG BasicAuthenticationFilter:118 - Authorization header: null
14:30:28,234 DEBUG FilterChainProxy:351 - /login.htm at position 7 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.savedrequest.RequestCacheAwareFilter@10f0f6ac'
14:30:28,235 DEBUG DefaultSavedRequest:309 - pathInfo: both null (property equals)
14:30:28,235 DEBUG DefaultSavedRequest:309 - queryString: both null (property equals)
14:30:28,235 DEBUG DefaultSavedRequest:331 - requestURI: arg1=/vicinity/member/member_home.htm; arg2=/vicinity/login.htm (property not equals)
14:30:28,235 DEBUG HttpSessionRequestCache:72 - saved request doesn't match
14:30:28,236 DEBUG FilterChainProxy:351 - /login.htm at position 8 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3bd29ee4'
14:30:28,236 DEBUG FilterChainProxy:351 - /login.htm at position 9 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.AnonymousAuthenticationFilter@bda96b'
14:30:28,236 DEBUG AnonymousAuthenticationFilter:98 - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6fa843a8: Principal: anonymousUser; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffd3270: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: DC9231E2B140D2F7D720A3B171B52CCF; Granted Authorities: ROLE_ANONYMOUS'
14:30:28,237 DEBUG FilterChainProxy:351 - /login.htm at position 10 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.session.SessionManagementFilter@23bdb02e'
14:30:28,237 DEBUG FilterChainProxy:351 - /login.htm at position 11 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.ExceptionTranslationFilter@7a79ae56'
14:30:28,237 DEBUG FilterChainProxy:351 - /login.htm at position 12 of 12 in additional filter chain; firing Filter: 'org.springframework.security.web.access.intercept.FilterSecurityInterceptor@4aa4ceeb'
14:30:28,237 DEBUG DefaultFilterInvocationSecurityMetadataSource:177 - Converted URL to lowercase, from: '/login.htm'; to: '/login.htm'
14:30:28,238 DEBUG DefaultFilterInvocationSecurityMetadataSource:204 - Candidate is: '/login.htm'; pattern is /member/**; matched=false
14:30:28,238 DEBUG DefaultFilterInvocationSecurityMetadataSource:204 - Candidate is: '/login.htm'; pattern is /login.htm; matched=true
14:30:28,238 DEBUG FilterSecurityInterceptor:192 - Secure object: FilterInvocation: URL: /login.htm; Attributes: [IS_AUTHENTICATED_ANONYMOUSLY]
14:30:28,239 DEBUG FilterSecurityInterceptor:293 - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6fa843a8: Principal: anonymousUser; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffd3270: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: DC9231E2B140D2F7D720A3B171B52CCF; Granted Authorities: ROLE_ANONYMOUS
14:30:28,239 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.RoleVoter@a0ccc96, returned: 0
14:30:28,239 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.AuthenticatedVoter@4e4b9101, returned: 1
14:30:28,239 DEBUG FilterSecurityInterceptor:214 - Authorization successful
14:30:28,240 DEBUG FilterSecurityInterceptor:224 - RunAsManager did not change Authentication object
14:30:28,240 DEBUG FilterChainProxy:340 - /login.htm reached end of additional filter chain; proceeding with original chain
14:30:28,243 DEBUG ExceptionTranslationFilter:101 - Chain processed normally
14:30:28,243 DEBUG SecurityContextPersistenceFilter:90 - SecurityContextHolder now cleared, as request processing completed
A: 

Here is the applicationContext-security.xml file (forced to post this as an answer to my own question as my posts kept getting truncated - how else can you make long posts??)

<?xml version="1.0" encoding="UTF-8"?>

    <!--
     - Sample namespace-based configuration - - $Id: applicationContext-security.xml 3911 2009-09-29 16:18:01Z ltaylor $
    -->

<beans:beans xmlns="http://www.springframework.org/schema/security" 
       xmlns:beans="http://www.springframework.org/schema/beans"
       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.0.xsd"&gt;

    <global-method-security pre-post-annotations="enabled">
     <!--
      AspectJ pointcut expression that locates our "post" method and applies security that way <protect-pointcut
      expression="execution(* bigbank.*Service.post*(..))" access="ROLE_TELLER"/>
     -->
    </global-method-security>

    <http auto-config="true">
     <intercept-url pattern="/member/**" access="ROLE_TELLER" />
     <intercept-url pattern="/login.htm" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
     <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />

     <form-login login-page="/login.htm"/>

        <session-management>
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="false" />
        </session-management>

     <!-- Required for development environments -->
        <port-mappings>
          <port-mapping http="8080" https="8443"/>
        </port-mappings>
    </http>

    <!--
     Usernames/Passwords are rod/koala dianne/emu scott/wombat peter/opal
    -->
    <authentication-manager>
     <authentication-provider>
      <password-encoder hash="md5" />
      <user-service>
       <user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
       <user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" />
       <user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a" authorities="ROLE_USER" />
       <user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_USER" />
      </user-service>
     </authentication-provider>
    </authentication-manager>

</beans:beans>
chrisjleu
+1  A: 

The key here is that the session is lost after the successful login:

14:30:28,218 DEBUG HttpSessionSecurityContextRepository:133 - No HttpSession currently exists
14:30:28,218 DEBUG HttpSessionSecurityContextRepository:91 - No SecurityContext was available from the HttpSession: null. A new one will be created.

The anonymous user is created by defult because there is no security context.

Can you try the same but without the https restriction? or do it all in https. Just to see if it works.

rodrigoap
Yes this is the problem. I've tried what you suggested and it works with HTTPS completely disabled or with it enabled for every page. The question now is how do I have it only work for the login page since this is the only part I would like to be secure?
chrisjleu