java - 属性 'passwordEncoder' 在 Spring Security 中抛出异常

标签 java spring spring-mvc spring-security

在我的网络应用程序上部署时出现此错误

    Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name
    'org.springframework.security.filterChains': Cannot resolve reference to bean 
    'org.springframework.security.web.DefaultSecurityFilterChain#1' while setting bean property
    'sourceList' with key [1]; nested exception is 
     org.springframework.beans.factory.BeanCreationException: Error creating bean with name
    'org.springframework.security.web.DefaultSecurityFilterChain#1': Cannot resolve      reference to bean 
   'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0'
    while setting constructor argument with key [3]; nested exception is 
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name
    'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0': 
    Cannot resolve reference to bean 'org.springframework.security.authentication.ProviderManager#0' while setting bean property
   'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name
    'org.springframework.security.authentication.ProviderManager#0': Cannot resolve reference to bean
    'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0' while setting constructor argument; nested exception is 
   org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0': 
 FactoryBean threw exception on object creation; nested exception is 
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name
 'org.springframework.security.authenticationManager': Cannot resolve reference to bean 
 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0' while
 setting constructor argument with key [0]; nested exception is 
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name
 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0': Error 
  setting property values; nested exception is 
 org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:

PropertyAccessException 1: org.springframework.beans.MethodInvocationException:
Property 'passwordEncoder' threw exception; nested exception is java.lang.NullPointerException

        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:326)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:350)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:154)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1417)

我的 spring-security.xml 有

<authentication-manager>
            <authentication-provider user-service-ref="customUserDetailsService">
                    <password-encoder ref="customEnocdePassword" >
                        <salt-source user-property="email"/>
                    </password-encoder>
            </authentication-provider>
    </authentication-manager>  


    <beans:bean id="customEnocdePassword" class="com.mycom.myproject.service.impl.service.impl.CustomEnocdePassword" />
    <beans:bean id="exceptionMapper" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler" >

我的 CustomEnocdePassword.java 是

public class CustomEnocdePassword implements PasswordEncoder {

    @Resource(name="userService")
    private UserService userService;

    @Override
    public String encodePassword(String password, Object username)
            throws DataAccessException {
        if (StringUtils.isBlank(password)) {
            throw new IllegalArgumentException("Password cannot be empty");
        }

        if(username.equals(null)){
            throw new IllegalArgumentException("Username cannot be null");
        }

        String saltPassword = getSaltPassword(username);


        String enteredPassword = getEnteredPassword(password, saltPassword);
        return enteredPassword;
    }


    @Override
    public boolean isPasswordValid(String encPassword, String password, Object username)
            throws DataAccessException {
        if (StringUtils.isBlank(password)) {
            return false;
        }

        String saltPassword = null;
        String databasePassword = null;

        try {
            User domainUser = userService.getUserByName(username.toString());
             saltPassword = domainUser.getPasswordSalt();
             databasePassword = domainUser.getCryptedPassword();
        } catch (LoginException e1) {
            e1.printStackTrace();
        }


        String enteredPassword = getEnteredPassword(password, saltPassword);


         return StringUtils.equals(databasePassword, enteredPassword);
        //return StringUtils.equals(databasePassword, password);
    }

    /**
     * @param password
     * @param saltPassword
     * @return
     */
    public static String getEnteredPassword(String password, String saltPassword) {
        String enteredPassword = null;

            try {
                enteredPassword = CryptoUtils.encrypt(password + saltPassword);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchProviderException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        return enteredPassword;
    }

    /**
     * @param username
     * @return
     */
    private String getSaltPassword(Object username) {
        String saltPassword = null;
        try {
            User domainUser = userService.getUserByName(username.toString());
             saltPassword = domainUser.getPasswordSalt();
        } catch (LoginException e1) {
            e1.printStackTrace();
        }
        return saltPassword;
    }

}

customUserDetailsS​​ervice.java 是

@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService extends CommonService implements UserDetailsService {

    static final Logger logger = Logger.getLogger(CustomUserDetailsService.class);

    @Resource(name="userService")
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String email)
            throws UsernameNotFoundException, DataAccessException {
        UserDetailedBean domainUser = null;


            try {




                domainUser = userService.getUserByName(email);      

                //userService.getUserDetailFromSpringSecurity();




                domainUser.isEnabled();
                domainUser.isAccountNonExpired();
                domainUser.isCredentialsNonExpired();
                domainUser.isAccountNonLocked();


        //Collection<? extends GrantedAuthority> roles =  getAuthorities((long) domainUser.getRoleId());



        } catch (AccountStatusException e) {
            logger.error("Invalid Login. "+email,e);
            throw new RuntimeException(e);
        } catch (TrialPeriodException e) {
            e.printStackTrace();
        }  catch (LoginException e) {
            throw new UsernameNotFoundException("Username not found. Please try again.");
        }

            return domainUser;
    }

    /**
     * Retrieves a collection of {@link GrantedAuthority} based on a numerical role
     * @param role the numerical role
     * @return a collection of {@link GrantedAuthority
     */
    public static final Collection<? extends GrantedAuthority> getAuthorities(Long role) {
        List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
        return authList;
    }


    /**
     * Converts a numerical role to an equivalent list of roles
     * @param role the numerical role
     * @return list of roles as as a list of {@link String}
     */
    public static List<String> getRoles(Long role) {
        List<String> roles = new ArrayList<String>();

        if (role.intValue() == 1) {
            roles.add("ROLE_USER");
            roles.add("ROLE_ADMIN");
            roles.add("ROLE_SJADMIN");          
        } else if (role.intValue() == 2) {
            roles.add("ROLE_USER");
            roles.add("ROLE_ADMIN");
        }else if (role.intValue() == 3) {
            roles.add("ROLE_USER");
            roles.add("ROLE_ADMIN");
        }else{
            roles.add("ROLE_USER");
        }

        return roles;
    }

    /**
     * Wraps {@link String} roles to {@link SimpleGrantedAuthority} objects
     * @param roles {@link String} of roles
     * @return list of granted authorities
     */
    public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for (String role : roles) {
            authorities.add(new SimpleGrantedAuthority(role));
        }
        return authorities;
    }

}

我没有得到我所缺少的东西。

如果您需要更多信息,请告诉我。

--- 更新 26-09-2014--

我的 Pom.xml

http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.mycom project 1.0 pom myproject

<properties>
    <spring.version>3.0.7.RELEASE</spring.version>
</properties>

<dependencies>
    <!--Joda time -->
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.1</version>
    </dependency>

    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time-jsptags</artifactId>
        <version>1.1.1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>3.1.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>3.1.1.RELEASE</version>
    </dependency>
    <!--spring -->

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>


    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-web</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.7.2</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.7.2</version>
    </dependency>


    <!-- <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> 
        <version>${spring.version}</version> <scope>test</scope> </dependency> -->

    <!-- <dependency> <groupId>org.springframework</groupId> <artifactId>spring-support</artifactId> 
        <version>2.0.8</version> </dependency> -->
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<modules>       
    <module>core</module>
    <module>imageutils</module>
    <!-- <module>highriseapi</module> -->
</modules>

--- 2014年9月29日更新---

Spring-security.xml

<?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" 
 xmlns:p="http://www.springframework.org/schema/p" 
 xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security.xsd
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util.xsd">
<http pattern="/resources" security="none" />



<http auto-config="true"  use-expressions="true">
    <intercept-url pattern="/login.htm" access="permitAll"/>
    <intercept-url pattern="/logout.htm" access="permitAll"/>
    <intercept-url pattern="/forgotPasswordForm" access="permitAll"/>
    <intercept-url pattern="/registrationForm" access="permitAll"/>     
    <intercept-url pattern="/home.htm" access="hasRole('ROLE_USER')"/>




    <form-login login-page="/login.htm" 
                authentication-failure-url="/loginfailed"
                default-target-url="/index.htm" 
                always-use-default-target="false"
                />

    <access-denied-handler error-page="/logout.htm"/>

    <logout invalidate-session="true" 
        logout-url="/logout.htm"
        success-handler-ref="userController"/>
        <remember-me data-source-ref="datasource" />
    <!--<remember-me user-service-ref="customUserDetailsService" key="89dqj219dn910lsAc12" use-   secure-cookie="true"  token-validity-seconds="466560000"/>-->
 <session-management session-authentication-strategy-ref="sas"/>
</http>





  <authentication-manager>
        <authentication-provider user-service-ref="customUserDetailsService">
                <password-encoder ref="customEnocdePassword" >
                    <salt-source user-property="email"/>
                </password-encoder>
        </authentication-provider>
</authentication-manager>  

 <!-- <beans:bean id="expirationChecker" class="com....service.impl.utility.UserTrialPeriodExpirationChecker" />  -->
<beans:bean id="customEnocdePassword" class="com....service.impl.service.impl.CustomEnocdePassword" />
<beans:bean id="exceptionMapper" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler" >
<beans:property name="exceptionMappings">
    <beans:map>
        <beans:entry key="com....exception.TrialPeriodExpiredException" value="/pricing"/>
        <beans:entry key="com....service.impl.exception.LoginException" value="/login?message=Invalid login"/>
    </beans:map>
</beans:property>
</beans:bean>

<beans:bean id="sas"
    class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="maximumSessions" value="3" />

最佳答案

我认为 CustomEnocdePassword 中的以下代码导致了您的问题:

if(username.equals(null)){
  throw new IllegalArgumentException("Username cannot be null");
}

替换为

if(username==null)){
  throw new IllegalArgumentException("Username cannot be null");
}

根据堆栈跟踪,spring 在设置 DaoAuthenticationProvider bean 的 passwordEncoder 属性时遇到 NPE。如果你看一下setter方法中,您会看到它调用 passwordEncoder.encodePassword(USER_NOT_FOUND_PASSWORD, null);,这会导致当前代码中出现空指针。

另请注意,org.springframework.security.authentication.encoding.PasswordEncoder 现已弃用。

关于java - 属性 'passwordEncoder' 在 Spring Security 中抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23091410/

相关文章:

java - Spring MVC - 将空日期作为参数传递

java - 了解 Spring-MVC 应用程序中数据绑定(bind)的概念

model-view-controller - Spring 3 的 MVC 框架生产质量中的 REST 支持了吗?

java - Spring MVC 无法实例化表单内的接口(interface)字段

java - Hibernate:Criteria Query child objects (associations) by Entity (not Id)

java - Android 开发 DropboxUnlinkedException

java - 如何从可执行 jar 读取本地属性文件?

java - 当 jackson 反序列化失败时, Jersey 异常映射器不工作

java - 在 Junit 测试中禁用 Spring @EnableScheduling

java - 同一个 Java 类的多个 MongoDB 集合名称