Hi,
I am taking a hands-on approach to Spring Security by trying to implement it on a website that I am creating. I have successfully managed to:
- login with the default login form
- login with my own login form (and logout too!)
- login using credentials stored in database (plaintext)
...but I have got stuck with trying to login using encryption. Here are the relevant code snippets:
spring-security.xml
Code:<?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-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"> <http auto-config="true"> <intercept-url pattern="/login.htm" access="ROLE_ANONYMOUS" /> <intercept-url pattern="/logout.htm" access="ROLE_ANONYMOUS" /> <intercept-url pattern="/resources/**" filters="none" /> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page="/login.htm" default-target-url="/home.htm" authentication-failure-url="/login.htm?error=true" /> <logout logout-success-url="/logout.htm" /> </http> <authentication-manager> <authentication-provider> <!--<password-encoder hash="sha"/>--> <password-encoder base64="true" ref="passwordEncoder"/> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select USER_NAME, PASSWORD, ENABLED from apphub.users where USER_NAME=?" authorities-by-username-query="select u.USER_NAME, ur.AUTHORITY from apphub.users u, apphub.user_roles ur where u.USER_ID = ur.USER_ID and u.USER_NAME=?" /> </authentication-provider> </authentication-manager> </beans:beans>
<app_name>-servlet.xml
Code:<!-- Start: Datasources --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/apphub" /> <property name="username" value="root" /> <property name="password" value="password" /> </bean> <!-- End: Datasources --> <!-- Start: Password Encoder --> <bean class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" id="passwordEncoder"/> <bean class="com.classifieds.security.DatabaseBootstrapPasswordEncoder" init-method="secureDatabase" depends-on="dataSource"> <property name="dataSource" ref="dataSource" /> <property name="passwordEncoder" ref="passwordEncoder" /> </bean> <!-- End: Password Encoder --> </beans>
DatabaseBootstrapPasswordEncoder.java
I have turned up the logging for Spring and I can see the following error:Code:package com.classifieds.security; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.security.authentication.encoding.PasswordEncoder; /** * A class, which will encode the bootstrap passwords loaded via SQL. * * NB: the application assumes a number of accounts will have been set up in the database * using a SQL script. These are considered 'bootstrap' accounts and the passwords for * these accounts will appear in the database in plain-text. The purpose of this class is * to encode the plain-text passwords of the bootstrap accounts. The class executes an init * method, which is invoked after the embedded-database bean is instantiated. * * @author Dan.Mortimer */ public class DatabaseBootstrapPasswordEncoder extends JdbcDaoSupport { private PasswordEncoder passwordEncoder; private final Log logger = LogFactory.getLog(getClass()); /** * @param passwordEncoder the passwordEncoder to set */ public void setPasswordEncoder(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } /** * The init method, which is invoked after the embedded-database bean is instantiated. * Spring JdbcTemplate functionality is used to loop through all the users in the database * and encode the password using the injected PasswordEncoder reference. Each password is * updated individually. */ public void secureDatabase() { getJdbcTemplate().query("select USER_NAME, PASSWORD from apphub.users", new RowCallbackHandler() { public void processRow(ResultSet rs) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); String encodedPassword = passwordEncoder.encodePassword(password, null); getJdbcTemplate().update("update apphub.users set PASSWORD = ? where USER_NAME = ?", encodedPassword, username); logger.info("Updating password for username:" + username + " to:" + encodedPassword); } }); } }
2012-07-23 14:05:40,125 DaoAuthenticationProvider [DEBUG] Authentication failed: password does not match stored value
The problem is that the password I get directly out of the database DOES match with what gets created in the java class. So I cannot understand what is going wrong.
I'd be very grateful for some advice, please!


Reply With Quote
assword), output in the log is as follows:
