Using Spring-Security PasswordEncoder with default authentication provider?
I am using Spring 4.0.8 RELEASE and Spring-Security 3.2.5 RELEASE
I am creating a REST WebService using an HTTP Digest that only registered users have access to.
My web.xml:
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
ApplicationContext.xml contains my controller / DAO important for this:
<import resource="security-context.xml" />
<bean id="daoPersonal" class="com.test.dao.PersonalDAO">
<property name="dataSource" ref="dataSource" />
</bean>
The security-context.xml now looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<debug />
<http entry-point-ref="digestEntryPoint">
<headers />
<intercept-url pattern="/**" access="ROLE_USER" />
<custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
</http>
<beans:bean id="digestFilter" class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
<beans:property name="userDetailsService" ref="daoPersonal" />
<beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
</beans:bean>
<beans:bean id="digestEntryPoint" class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
<beans:property name="realmName" value="Contacts Realm via Digest Authentication" />
<beans:property name="key" value="acegi" />
</beans:bean>
<beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<authentication-manager>
<authentication-provider user-service-ref="daoPersonal">
<password-encoder ref="bcryptEncoder" />
</authentication-provider>
</authentication-manager>
</beans:beans>
and my PersonalDAO
public class PersonalDAO extends NamedParameterJdbcDaoSupport implements UserDetailsService {
/*my other code
...
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println(new Date() + " PersonalDAO loadUserByUsername: " + username);
List<UserDetails> users = getJdbcTemplate().query(USER_QUERY, new String[] {username}, new RowMapper<UserDetails>() {
public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
String username = rs.getString(1);
String password = rs.getString(2);
boolean enabled = true;
Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
auths.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(username, password, enabled, true, true, true, auths);
}
});
if(users.size()==0){
throw new UsernameNotFoundException("");
}
System.out.println(new Date() + "Users Found: " + users.size());
return users.get(0);
}
}
Without a password encoder inside the authentication provider, it works as intended using plaintext passwords from the database. But with the encoder password (and the password in the db was changed to bcrypt encoded code), the browser states that the login was wrong and asks again. From my output, I can see that my PersonalDAO was called and found the user.
I still have another user in my db that still has a cleartext password, I tried to log in with this but with bcryptencoder active I get this in my server log:
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder matches
WARNING: Encoded password does not look like BCrypt
Now I can at least see that the BCryptEncoder call is being called, but it got a match, which means nothing is encoded and I still can't log in. (which one would expect).
What am I missing?
edit:
The log output isn't much, but here goes:
Fri Dec 05 15:07:06 CET 2014 PersonalDAO loadUserByUsername: test
Fri Dec 05 15:07:06 CET 2014 Users Found: 1
encrypted password in db: $ 2a $ 10 $ HWX95PBi7pob2bmIHXka3ecMcfsSvEifV3Z6J0CAb3vpWs8N9j5xS
source to share