Spring Security 2.0: NTLM filter with custom UserDetailsService

I used this blog to get started: http://blog.mediasoft.be/ntlm-with-spring-security-20/

My Application-context is pretty much as per the Spring 2.0 configuration at the bottom of the post, with the following changes:

  • Different properties for the ntlm filter
  • servlet-api-provision=”false” on the <security:http> tag
  • Addition of custom UserDetailsService.

The full config is below:

<security:authentication-manager alias="_authenticationManager" />

    <bean id="authenticationProvider"
     class="com.mydomain.security.UserDetailsAuthenticationProvider">
        <security:custom-authentication-provider />
        <property name="userDetailsService" ref="userDetailsService" />
    </bean>

    <bean id="userDetailsService" class="com.mydomain.security.UserDetailsServiceImpl">
        <property name="daoUser" ref="daoUser" />
    </bean>

    <bean id="ntlmFilter" class="org.springframework.security.ui.ntlm.NtlmProcessingFilter">
        <security:custom-filter position="NTLM_FILTER" />
        <property name="stripDomain" value="true" />
        <property name="defaultDomain" value="mydomain.com" />
        <property name="domainController" value="mycontroller" />
        <property name="authenticationManager" ref="_authenticationManager" />
    </bean>

    <bean id="ntlmEntryPoint"
     class="org.springframework.security.ui.ntlm.NtlmProcessingFilterEntryPoint">
        <property name="authenticationFailureUrl" value="/denied.xhtml" />
    </bean>

    <bean id="exceptionTranslationFilter"
     class="org.springframework.security.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint" ref="ntlmEntryPoint" />
    </bean>

    <security:http access-denied-page="/denied.xhtml"
     entry-point-ref="ntlmEntryPoint" servlet-api-provision="false">
        <security:intercept-url pattern="/denied.xhtml" filters="none" />
        <security:intercept-url pattern="/**" access="ROLE_USER" />
    </security:http>

My UserDetailsAuthenticationProvider is exactly as per the blog.

My UserDetails Service is below. Note that the UserDetails created should have blank password. This confused me for a bit.

public class UserDetailsServiceImpl implements UserDetailsService {
	private UserDAO daoUser;
	private static Logger log = Logger.getLogger(UserDetailsService.class);

	public UserDAO getDaoUser() {
		return daoUser;
	}

	public void setDaoUser(UserDAO daoUser) {
		this.daoUser = daoUser;
	}

	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {

		MyUser user;

		try {
			user = daoUser.getUser(username);
		} catch (DAOException ex) {
			throw new DataRetrievalFailureException(ex.getMessage());
		}

        if (user != null) {

            ArrayList<GrantedAuthority> ga = new ArrayList<GrantedAuthority>();
            ga.add(new GrantedAuthorityImpl("ROLE_USER"));
            GrantedAuthority[] grantedAuthorities = new GrantedAuthority[ga.size()];
            ga.toArray(grantedAuthorities);

            UserDetailsImpl ud = new UserDetailsImpl(username, "", true, grantedAuthorities, user);
            return ud;
        } else {
            throw new UsernameNotFoundException("Username Not Found");
	}
}

My UserDetailsImpl simply extends org.springframework.security.userdetails.User and has an additional field for my ‘MyUser’

public class UserDetailsImpl extends org.springframework.security.userdetails.User {

	private static final long serialVersionUID = 1584153957347843760L;

	private MyUser user;

	public UserDetailsImpl(String username, String password, boolean enabled,
			 GrantedAuthority[] authorities, MyUser user)
			throws IllegalArgumentException {
		super(username, password, enabled, true, true,
				true, authorities);
		this.user = user;
	}

	public MyUser getUser() {
		return user;
	}

	public void setUser(MyUser user) {
		this.user = user;
	}
}

And that seems to work. Now I am trying to enable method level security, so more to come soon…