Results 1 to 6 of 6

Thread: Pass Multiple Headers to UserDetailsService

  1. #1
    Join Date
    Jul 2010
    Posts
    3

    Default Pass Multiple Headers to UserDetailsService

    This is my first post, so let me know if I'm not following posting protocol properly.

    My application uses Shibboleth/Spring Security and I am trying to pass multiple headers to UserDetailsService because I have to look up the user by different fields. My configuration looks the one at

    http://static.springsource.org/sprin...e/preauth.html

    i.e.

    Code:
     
    <security:http>
        <!-- Additional http configuration omitted -->
        <security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
      </security:http>
    
        <bean id="siteminderFilter" class=
    "org.springframework.security.web.authentication.preauth.header.RequestHeaderAuthenticationFilter">
        <property name="principalRequestHeader" value="SM_USER"/>
        <property name="authenticationManager" ref="authenticationManager" />
      </bean>
    
      <bean id="preauthAuthProvider"
    class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <property name="preAuthenticatedUserDetailsService">
          <bean id="userDetailsServiceWrapper"
              class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <property name="userDetailsService" ref="userDetailsService"/>
          </bean>
        </property>
        </bean>
    
        <security:authentication-manager alias="authenticationManager">
          <security:authentication-provider ref="preauthAuthProvider" />
        </security-authentication-manager>
    How can I accomplish doing something like :

    Code:
        <bean id="siteminderFilter" class=
    "org.springframework.security.web.authentication.preauth.header.RequestHeaderAuthenticationFilter">
        <property name="principalRequestHeader1" value="LOCAL_ID"/>
        <property name="principalRequestHeader2" value="GLOBAL_ID"/>
        <property name="principalRequestHeader3" value="OTHER_ID"/>
        <property name="authenticationManager" ref="authenticationManager" />
      </bean>
    Any help is appreciated

  2. #2
    Join Date
    Jan 2008
    Posts
    1,826

    Default

    Do you need all the fields at once or just individually? If you need them individually you can create three instances of the filter one with each of the headers. Make sure that the first two do not have the exceptionIfHeaderMissing set to true. An alternative (and cleaner approach) would be to extend the AbstractPreAuthenticatedProcessingFilter. This would work even if you needed only one of the fields or if you needed all the fields at once.
    Rob Winch - @rob_winch
    Spring Security Lead
    Pivotal

  3. #3
    Join Date
    Jul 2010
    Posts
    3

    Default

    I need all fields at once so I will try your second suggestion. Thank you!

  4. #4
    Join Date
    Jul 2010
    Posts
    3

    Default

    As a follow up to my question (let me know if I should start a new thread) I implemented my own RequestHeaderAuthenticationFilter which grabs all the header fields that I need.
    Now, when I pass it to my UserDetailsService implementation, I need to pass all the fields to loadUserByUsername so the correct User is load.

    The problem is that loadUserByUsername takes a String as a parameter.

    The reason I need to do this is that my authentication service is federated so the loadUserByUsername method has to figure out which field to use to retrieve the user, i.e.

    1. look up user in the "local" population by username1
    2. if none found, look up user in the "global" population by username2, etc.

    So I have to somehow pass all of the usernames as a map to loadUserByUsername.

    The only way I could think of doing this is converting the map to a string, passing it to loadUserByUsername and then parsing the Map. This is definitely a hack.

    Any ideas on a cleaner way to do this?


    Thank you!

  5. #5
    Luke Taylor is offline Senior Member Acegi Security System TeamSpring Team
    Join Date
    Aug 2004
    Location
    Glasgow, Scotland
    Posts
    3,449

    Default

    Quote Originally Posted by dotcom View Post

    The problem is that loadUserByUsername takes a String as a parameter.
    The preAuthenticatedUserDetailsService is actually an AuthenticationUserDetailsService, so you can implement this directly. If you look at your configuration, you are using a wrapper which creates the actual instance from a basic UserDetailsService.

    Either that or you can implement the AuthenticationProvider directly.
    Spring - by Pivotal
    twitter @tekul

  6. #6
    Join Date
    Oct 2011
    Posts
    1

    Default

    Quote Originally Posted by dotcom View Post
    The problem is that loadUserByUsername takes a String as a parameter.
    You can pass extra parameters as HTTP-headers and extract them from the request in loadUserByUsername().

    Add a RequestContextListener in web.xml
    Code:
    <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    In your UserDetailsService implementation
    Code:
    public EntityUserDetails loadUserByUsername...
    {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    ...

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •