简体   繁体   中英

BadCredentialsException is spring-security

continue my projects I encountered a problem in the authorization for accounts in Spring setsurity - Problems in the query to the database, all the settings are correct, the database is created at the start of the project, there is no error in debug but at login message pops up in the log:

(UserAuthentication.java:authenticate:56) tradeManager.DAO.Impl.CustomHibernateDaoSupport.find(CustomHibernateDaoSupport.java:60)
        tradeManager.service.authentication.UserAuthentication.authenticate(UserAuthentication.java:45)

...
Authentication request failed: org.springframework.security.authentication.BadCredentialsException: 
User does not exists!

I added few catches to get precise exception and got new NullPointerException

17:52:34.280:WARN::/tradeManager/j_spring_security_check
java.lang.NullPointerException
    at tradeManager.DAO.Impl.CustomHibernateDaoSupport.find(CustomHibernateDaoSupport.java:60)
    at tradeManager.service.authentication.UserAuthentication.authenticate(UserAuthentication.java:48)

Can someone explain me what i'm doing wrong? Please help me.

here's the code affected by the query:

@Service("userAuthentication")
public class UserAuthentication implements AuthenticationManager {

protected static Logger userAccessLogger = Logger.getLogger("userAccessLog");
private UserDAO userDAO = new UserDAOImpl();
private Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();

public Authentication authenticate(Authentication auth)
        throws UsernameNotFoundException {

    User user = null;

    /*
     * Init a database user object
     */
    try {
        // Retrieve user details from database
        //user = userDAO.find(auth.getName());
        List<User> list = userDAO.findAllByParam("username", auth.getName());
        user = (list.isEmpty()) ? null :  list.get(0);

    } catch (Exception e) {

        StackTraceElement[] stack = e.getStackTrace();
        String exception = "";
        for (StackTraceElement s : stack) {
            exception = exception + s.toString() + "\n\t\t";
        }
        userAccessLogger.error(exception);

        throw new BadCredentialsException("\n\tUser " + auth.getName() + " does not exists!\n");
    }

    /*
     * Compare passwords
     * Make sure to encode the password first before comparing
     */
     if (user != null) {
        if (passwordEncoder.isPasswordValid(user.getPassword(), (String) auth.getCredentials(), null)) {
            throw new BadCredentialsException("\n\tWrong password!\n");
        }
    }

    /*
     * main logic of authentication manager
     * Username and password must be the same to authenticate
     */
    if (auth.getName().equals(auth.getCredentials())) {
        throw new BadCredentialsException("Entered username and password are the same!");

    } else {
        assert user != null;
        return new UsernamePasswordAuthenticationToken(
                auth.getName(),
                auth.getCredentials(),
                getAuthorities(user.getAccess()));
    }
}

/*
 * Retrieves the correct ROLE type depending on the access level
 */
public Collection<GrantedAuthority> getAuthorities(Integer access) {
    // Create a list of grants for this user
    List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);

    userAccessLogger.debug("Grant ROLE_USER to this user");
    authList.add(new SimpleGrantedAuthority("ROLE_USER"));

    if (access.compareTo(1) == 0) {
        authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        userAccessLogger.debug("Grant ROLE_ADMIN to this user");
    }

    // Return list of granted authorities
    return authList;
}

here is CustomHibernateDaoSupport:

public class CustomHibernateDaoSupport<T> implements DAO<T> {
protected static Logger daoSupportLogger = Logger.getLogger("daoSupportLog");
private Class<T> clazz;
private SessionFactory sessionFactory;

public CustomHibernateDaoSupport(Class<T> clazz) {
    this.clazz = clazz;
}

@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}

private SessionFactory  getSessionFactory() {
    return sessionFactory;
}

@Override
@Transactional
public void save(T entity) {
    getSessionFactory().getCurrentSession().save(entity);
}

@Override
@Transactional
public void update(T entity) {
    getSessionFactory().getCurrentSession().update(entity);
}

@Override
@Transactional
public void delete(Serializable key) {
    Object entity = getSessionFactory().getCurrentSession().get(clazz, key);
    if (entity != null) {
        getSessionFactory().getCurrentSession().delete(entity);
    }
}

@Override
@Transactional
public T find(Serializable key) {
    return (T) getSessionFactory().getCurrentSession().get(clazz, key);
}

@Override
@Transactional
public List<T> findAll() {
    return getSessionFactory().getCurrentSession().createCriteria(clazz).list();
}

@Override
@Transactional
public List<T> findAllByParam(final String paramName, final Object paramValue) {
    return getSessionFactory().getCurrentSession().createCriteria(clazz)
            .add(Restrictions.eq(paramName, paramValue))
            .list();
}
}

the security settings are like this:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:security="http://www.springframework.org/schema/security"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/security
            http://www.springframework.org/schema/security/spring-security-3.1.xsd">



<!-- excluded from Security
<security:http pattern="/resources/*" security="none" />-->

<!-- Configuration of Spring-Security. Set to false to assign custom filters  -->

<security:http auto-config="false" use-expressions="true" access-denied-page="/crimea/auth/denied"
               entry-point-ref="authenticationEntryPoint" >

    <security:logout invalidate-session="true"
                    logout-success-url="/crimea/auth/login"
                    delete-cookies="SPRING_SECURITY_REMEMBER_ME_COOKIE"
                    logout-url="/crimea/auth/logout"/>

    <security:intercept-url pattern="/crimea/auth/login" access="permitAll"/>
    <security:intercept-url pattern="/crimea/main/admin" access="hasRole('ROLE_ADMIN')"/>
    <security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_ADMIN','ROLE_USER')"/>

    <security:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER"/>

</security:http>

<!-- Custom filter for username and password -->
<bean id="authenticationFilter"
      class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"
      p:authenticationManager-ref="userAuthentication"
      p:authenticationFailureHandler-ref="customAuthenticationFailureHandler"
      p:authenticationSuccessHandler-ref="customAuthenticationSuccessHandler"
      p:postOnly="false" />

<!-- Custom authentication manager. !!! Username and password must not be the same !!! -->
<bean id="userAuthentication" class="tradeManager.service.authentication.UserAuthentication" />

<!-- default failure URL -->
<bean id="customAuthenticationFailureHandler"
      class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
      p:defaultFailureUrl="/crimea/auth/login?error=true" />

<!-- default target URL -->
<bean id="customAuthenticationSuccessHandler"
      class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler"
      p:defaultTargetUrl="/crimea/main/common" />

<!-- The AuthenticationEntryPoint -->
<bean id="authenticationEntryPoint"
      class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"
      p:loginFormUrl="/crimea/auth/login" />

<!--  Spring Security autowire the parent property  -->
<security:authentication-manager/>

</beans>

I'm not showing User model becouse it standart. Acess is managed by Integer var:

   /**
     * Access level.
     * 1 = Admin role
     * 2 = Regular role
     */
    @Column(name = "Access", nullable = false)
    private Integer access;

Ок, didn't get any helpful answer, so tried my best. First of all, this line got my attention:

<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_ADMIN','ROLE_USER')"

I changed it to:

<security:intercept-url pattern="/crimea/main/common" access="hasRole('ROLE_USER')"

OK, I did more and changed query to username and I writed direct access, from:

list = userDAO.findAllByParam("from username",auth.getName());

to:

list = getSessionFactory().getCurrentSession().createCriteria(User.class)
                    .add(Restrictions.eq("username", auth.getName())).list();

and added the authentication session attributes to the class and start working He = (( So, can anyone explain to me why my CustomHibernateDaoSupport class does not work??

OK. I solved my problem ))

First of all? I changed location of @Repository("employeeDAOImpl")annotation. I changed SQL driver to com.jolbox.bonecp.BoneCPDataSource naw my datasourse config loks likr this:

<!-- for database, imports the properties from database.properties -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="idleConnectionTestPeriod" value="60"/>
    <property name="idleMaxAge" value="240"/>
    <property name="maxConnectionsPerPartition" value="30"/>
    <property name="minConnectionsPerPartition" value="10"/>
    <property name="partitionCount" value="3"/>
    <property name="acquireIncrement" value="5"/>
    <property name="statementsCacheSize" value="100"/>
    <property name="releaseHelperThreads" value="3"/>
</bean>

changed Spring shema to:

<tx:annotation-driven transaction-manager="transactionManager"/>
<mvc:annotation-driven />

in UserAuthentication class I added chek for NullPointer

 if (entity == null) {
        throw new BadCredentialsException("User does not exists!");
    }

added to pom.xml maven dep. for new sql driver:

<dependency>
        <groupId>com.jolbox</groupId>
        <artifactId>bonecp</artifactId>
        <version>0.8.0-rc1</version>
    </dependency>

So My Authentication is working perfect naw =))

I solved my problem

  • First, I changed the location of @Repository("employeeDAOImpl")annotation.
  • I changed SQL driver to com.jolbox.bonecp.BoneCPDataSource now my datasourse config looks like this:

     <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClassName}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="idleConnectionTestPeriod" value="60"/> <property name="idleMaxAge" value="240"/> <property name="maxConnectionsPerPartition" value="30"/> <property name="minConnectionsPerPartition" value="10"/> <property name="partitionCount" value="3"/> <property name="acquireIncrement" value="5"/> <property name="statementsCacheSize" value="100"/> <property name="releaseHelperThreads" value="3"/> </bean> 
  • changed Spring schema to:

    <tx:annotation-driven transaction-manager="transactionManager"/> <mvc:annotation-driven />

  • in UserAuthentication class I added check for a null

    if (entity == null) { throw new BadCredentialsException("User does not exists!"); }

  • added to pom.xml maven dep. for new sql driver:

    com.jolbox bonecp 0.8.0-rc1

So my authentication is working perfect now =))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM