Announcement Announcement Module
Collapse
No announcement yet.
Injection of Principal into MVC Controller Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Injection of Principal into MVC Controller

    I've just moved my spring security configuration (3.1.1) from using the security namespace to manual bean definitions.
    I seem to have everything working fine ... however the Principal that was injected into my (Spring MVC) controllers is now null! When using the security namespace configuration the principal is injected fine.
    I can get around the issue by accessing the principal via the SecurityContextHolder but it isn't very neat.

    Code:
    	
            @RequestMapping(value="/home", method = RequestMethod.GET)
    	public String home(ModelMap model, Principal principal ) {
                  // principal is null here so the following will throw a NullPointerException !!
                  String theUsername = principal.getName();
    
                  // The following is fine and gets me the username
                  User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                  String username = user.Username();
    I'm really not sure where to look to get to the bottom of this one - any ideas?

  • #2
    You probably missed a filter or did configure the wrong order of filters (also is there a reason why you moved away from the namespace and do everything with plain beans?!).

    Make sure you have the SecurityContextHolderAwareRequestFilter configured.

    Comment


    • #3
      Thanks Marten,

      It was indeed the SecurityContextHolderAwareRequestFilter that I wasn't using.
      My filter chain was set up as ;
      Code:
      <security:filter-chain pattern="/checkout*" filters="
                securityContextPersistenceFilter,
                logoutFilter,
                usernamePasswordAuthenticationFilter,
                rememberMeAuthenticationFilter,
                anonymousAuthenticationFilter,
                exceptionTranslationFilter,
                filterSecurityInterceptor"/>
      I added in the SecurityContextHolderAwareRequestFilter after the rememberMeAuthenticationFilter and the Principal is back!

      The reason I moved away from the namespace was first to gain a fuller understanding of the security design but also that I need to apply certain logic everytime someone is authenticated and felt that using an authentication event listener was the best way to do it. I don't believe you can use listeners with the namespace.

      Thanks again for your help.

      Comment


      • #4
        That still doesn't mean you have to move away from the namespace configuration you can just reconfigure the part you need instead of configuring everything.

        Comment


        • #5
          Yes - that might be better for me - but I wasn't sure this was possible.

          If I have understood the reference guide correctly, in order to add a listener I would need to define the authentication manager as a bean rather than via the namespace (which doesn't provide a hook for an authentication event publisher).

          So something like ..
          Code:
          	<bean id="myAuthenticationManager" class="org.springframework.security.authentication.ProviderManager">
          		<constructor-arg>
          			<list>
          				<ref local="daoAuthenticationProvider"/>
          				<ref local="anonymousAuthenticationProvider"/>
          				<ref local="rememberMeAuthenticationProvider"/>
          			</list>
          		</constructor-arg>
          		<property name="authenticationEventPublisher" ref="defaultAuthEventPublisher"/>
          	</bean>
          .. and I would therefore also need to define the providers as beans in addition to the other required beans such as password encoders, user details service, etc...

          However, once I've explicitly defined the authentication manager as a bean don't I need to explicitly define the filters (UsernamePasswordAuthenticationFilter, FilterSecurityInterceptor, RememberMeAuthenticationFilter) so that they can point to this manager? E.g.
          Code:
          	<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
          		<property name="authenticationManager" ref="myAuthenticationManager"/>
          		<property name="accessDecisionManager" ..... />
          		<property name="securityMetadataSource">
          			<security:filter-security-metadata-source use-expressions="true">
          				<security:intercept-url pattern="/orders*" access="authenticated"/>
                                           ...
          			</security:filter-security-metadata-source>
          		</property>
          	</bean>
          And the FilterSecurityInterceptor can't be replaced if created via the <http> element so I'd have to define the filter chain explicitly?

          Or have I missed something somewhere and there is a way of defining an authentication manager to use an event publisher but not having to stop using namespace <http> tags?

          Comment


          • #6
            I strongly suggest the reference guide. You can simply specify which authenticationmanager to use by adding the authentication-manager-ref attribute to the http namespace.

            However, once I've explicitly defined the authentication manager as a bean don't I need to explicitly define the filters (UsernamePasswordAuthenticationFilter, FilterSecurityInterceptor, RememberMeAuthenticationFilter) so that they can point to this manager? E.g.
            Would be a pretty louse framework if, when you wanted to configure only a AuthenticationManager, you would need to configure everything by hand. (In short no you don't).

            Comment


            • #7
              Thanks a million - that hook (authentication-manager-ref) was what I'd missed when going through the reference guide.
              Thanks for setting me straight!
              I'll head in that direction, use the http element and just define the authentication manager, providers and beans that the providers need explicitly...

              Comment

              Working...
              X