Bonjour,

J'ai remarqué que certains sujets traitaient de ce problème mais aucun ne m'a apporté de réponse à mon problème.

J'essaye d'implémenter l'exemple du livre intitulé "Spring Security" et tout fonctionne bien excepté l'injection des éléments SaltSource et PasswordEncoder que j'ai pourtant définis dans le fichier applicationContext-business.xml comme suit:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
 <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>
    <bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
        <property name="userPropertyToUse" value="salt"/>
    </bean>
  <bean id="jdbcUserServiceCustom" class="springsecurity.security.CustomJdbcDaoImpl">
        <property name="dataSource" ref="dataSource"/>
        <property name="enableGroups" value="true"/> 
        <property name="enableAuthorities" value="true"/>
        <property name="usersByUsernameQuery">
            <value>SELECT username, password, enabled, salt FROM users WHERE username = ?</value>
        </property>
    </bean>
...
<context:annotation-config />
    <context:component-scan base-package="springsecurity.security"/>
J'obtiens un NullPointerExcpetion à l'invocation de la méthode changePassword:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
package springsecurity.security;
 
//imports...
 
public class CustomJdbcDaoImpl extends JdbcDaoImpl {
    // Ch 4 Password Encoder and Salt Exercise
 
    @Autowired
    private PasswordEncoder passwordEncoder;// = new Md5PasswordEncoder();
    @Autowired
    private SaltSource saltSource;
    //private ReflectionSaltSource saltSource = new ReflectionSaltSource();
 
    public void changePassword(String username, String password) {
        /*getJdbcTemplate().update(
                "UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?",
                password, username);*/
        // Ch 4 After password encoder and salt exercise using the username
        UserDetails user = loadUserByUsername(username);
        //saltSource.setUserPropertyToUse("salt");
        String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));
        getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", encodedPassword, username);
    }
Voici le fichier applicationContext-Security.xml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
 
 <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="jdbcUserServiceCustom">
            <password-encoder ref="passwordEncoder">
                <salt-source ref="saltSource"/>
            </password-encoder>
        </authentication-provider>
    </authentication-manager>
Voici le fichier dispatch servlet bank-servlet.xml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/jdbc
                           http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <bean name="/listAccounts.html" class="bigbank.web.ListAccounts">
        <constructor-arg ref="bankService"/>
    </bean>
 
    <bean name="/post.html" class="bigbank.web.PostAccounts">
        <constructor-arg ref="bankService"/>
    </bean>
    <bean id="viewResolver"  class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
 
    <context:annotation-config />
    <context:component-scan base-package="springsecurity.security"/>
</beans>
Voici mon fichier web.xml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext-business.xml
            /WEB-INF/applicationContext-security.xml
        </param-value>
    </context-param>
    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>tutorial.root</param-value>
    </context-param>
    <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>
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 <servlet>
        <servlet-name>bank</servlet-name> <!-- reference to bank-servlet.xml-->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>bank</servlet-name>
        <url-pattern>*.html</url-pattern>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
Et voici l'erreur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
 
ATTENTION: StandardWrapperValve[bank]: PWC1406: Servlet.service() for servlet bank threw exception
java.lang.NullPointerException
        at springsecurity.security.CustomJdbcDaoImpl.changePassword(CustomJdbcDaoImpl.java:40)
        at springsecurity.security.AccountController.submitChangePasswordPage(AccountController.java:43)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Il n'y a pas d'erreur au déploiement et tout fonctionne sans problème jusqu'à l'exécution de la méthode changePassword. Évidemment tout fonctionne aussi très bien si je contourne les injections en instanciant les objets directement dans le bean. Je tiens aussi a signaler qu'une injection de l'élément CustomJdbcDaoImpl dans le Bean AccountController avec l'annotation @Controller fonctionne elle très bien
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 
package springsecurity.security;
 
//imports
 
@Controller
public class AccountController extends BaseController {
 
    @Autowired
    private CustomJdbcDaoImpl changePasswordDao;
 
    @RequestMapping("home.do")
    public void accountHome() {
    }
 
    @RequestMapping(value = "changePassword.do", method = RequestMethod.GET)
    public void showChangePasswordPage() {
        System.out.println("GET submitChangePasswordPage");
    }
 
    @RequestMapping(value = "changePassword.do", method = RequestMethod.POST)
    public String submitChangePasswordPage(@RequestParam("password") String newPassword) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
 
        String username = principal.toString();
        if (principal instanceof UserDetails) {
            username = ((UserDetails) principal).getUsername();
        }
        System.out.println("USERNAME: "+username+" "+newPassword);
        changePasswordDao.changePassword(username, newPassword);
        SecurityContextHolder.clearContext();
 
        return "redirect:";//nothing means home
    }
}
Je vous remercie par avance.

Bou