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…