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

+3


source to share


1 answer


A combination of HTTP Digest Authentication and BCrypt Password Encoder is not possible. This is because the HTTP Digest algorithm requires the password to be stored in cleartext. You must either change the authentication method or remove the password encoding.



+6


source







All Articles