为什么Hibernate事务不更新我的数据库?

时间:2015-05-19 16:06:03

标签: java spring hibernate

我的登录课有问题。如果用户尝试使用用户名登录失败,则应禁用该用户帐户。在运行时,没有错误,但我的数据库没有任何变化。我通过Hibernate更新我的数据库是否有问题,我想我可以使用我的UserBean.class来访问属性,更改它们然后提交Hibernate事务?

这是我的LoginDAO.class:

package com.sga.app.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.context.internal.ManagedSessionContext;
import org.hibernate.criterion.Restrictions;
import org.owasp.encoder.Encode;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import com.sga.app.beans.UserBean;
import com.sga.app.hibernate.HibernateUtil;
import com.sga.app.security.LoginFailureEventListener;
import com.sga.app.security.XssRequestWrapper;

@Component("loginDAO")
@Transactional
@Configuration
public class LoginDAO implements
    ApplicationListener<AuthenticationFailureBadCredentialsEvent> {

private int loginAttemptsThreshold;
private int failedLoginAttempts;
private static Logger logger = Logger
        .getLogger(LoginFailureEventListener.class);
private static Session session;
private Criteria criteria;
private String username;
private boolean enabled;
private String forename;
private String authority;
private XssRequestWrapper xssReqWrapper;
private PreparedStatement prepStmtUsers;
private PreparedStatement prepStmtAuthorities;
private String URL = "jdbc:oracle:thin:system/sgaWebApp@localhost:1521/XE";
private String updateUsersStatement = "insert into users (username, password) 
  values (:username, :password)";
private String updateAuthoritiesStatement = "insert into authorities (username, 
  authority) values (:username, :authority)";

@Bean
public LoginDAO loginDAO() {
    return new LoginDAO();
}

public void setLoginAttemptsThreshold(int threshold) {
    this.loginAttemptsThreshold = threshold;
}

@Transactional
public void loginUser(UserBean user, BindingResult result) {

    try {
        Connection conn = DriverManager.getConnection(URL);
        // clean out any possible XSS injection
        String cleanUsernameValueInput = cleanOutXSSVulnerabilities("j_username");
        String cleanPasswordValueInput = cleanOutXSSVulnerabilities("j_password");
        // OWASP encoding
        String safeUsername = Encode.forHtml(cleanUsernameValueInput);
        prepStmtUsers.setString(1, safeUsername);
        String safePassword = Encode.forHtml(cleanPasswordValueInput);
        prepStmtUsers.setString(2, safePassword);
        prepStmtAuthorities.setString(1, safeUsername);
        String safeUserAuthority = Encode.forHtml(user.getAuthority());
        prepStmtAuthorities.setString(2, safeUserAuthority);
        // execute login process
        prepStmtUsers = conn.prepareStatement(updateUsersStatement);
        prepStmtAuthorities = conn
                .prepareStatement(updateAuthoritiesStatement);
        prepStmtUsers.executeUpdate();
        prepStmtAuthorities.executeUpdate();
        conn.close();
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (AccessDeniedException accessDenied) {
        accessDenied.printStackTrace();
    }
}

private String cleanOutXSSVulnerabilities(String input) {
    return xssReqWrapper.cleanXSS(input);
}

@Override
public void onApplicationEvent(
        AuthenticationFailureBadCredentialsEvent event) {
    if (event.getException().getClass()
            .equals(UsernameNotFoundException.class)) {
        return;
    }
    // print registration attempts to log file for security investigation if
    // required
    logger.info("Registration attempt failed: " + event.getException());
    logger.info("Registration attempt number: " + event.getTimestamp());
    String userId = event.getAuthentication().getName();
    logger.info("FAILED LOGIN ATTEMPT NUMBER "
            + recordLoginAttempts(userId));
    recordLoginAttempts(userId);
    if (recordLoginAttempts(userId) >= loginAttemptsThreshold) {
        lockoutUser(userId);
    }
}

private int recordLoginAttempts(String userId) {
    failedLoginAttempts++;
    return failedLoginAttempts;
}

@SuppressWarnings("unchecked")
private ArrayList<UserBean> getUserAccountDetails(String input) {
    ArrayList<UserBean> returnValues = new ArrayList<UserBean>();
    session = HibernateUtil.createSessionFactory().openSession();
    session.setFlushMode(FlushMode.MANUAL);
    ManagedSessionContext.bind(session);
    session.beginTransaction();
    criteria = session.createCriteria(UserBean.class);
    List<UserBean> retrievedUser = criteria.add(
            Restrictions.like("username", input)).list();
    for (UserBean userDetails : retrievedUser) {
        logger.debug("USERNAME INSIDE THE GET USER ACCOUNT DETAILS METHOD: "
                + userDetails.getUsername());
        logger.debug("AUTHORITY INSIDE THE GET USER ACCOUNT DETAILS METHOD: "
                + userDetails.getAuthority());
        returnValues.add(userDetails);
    }
    session.flush();
    session.getTransaction().commit();
    session.close();
    return returnValues;
}

private void lockoutUser(String userId) {
    ArrayList<UserBean> userAccountValues = getUserAccountDetails(userId);
    session = HibernateUtil.createSessionFactory().openSession();
    session.setFlushMode(FlushMode.MANUAL);
    ManagedSessionContext.bind(session);
    session.beginTransaction();
    for (UserBean user : userAccountValues) {
        username = user.getUsername();
        forename = user.getForename();
        enabled = user.getEnabled();
        authority = user.getAuthority();
        logger.debug("USERNAME: " + username);
        logger.debug("FORENAME: " + forename);
        logger.debug("ENABLED BEFORE CHANGE: " + enabled);
        user.setEnabled(false);
        logger.debug("AUTHORITY BEFORE CHANGE: " + authority);
        user.setAuthority("BLOCKED");
    }
    session.flush();
    session.getTransaction().commit();
    logger.debug("ENABLED AFTER CHANGE: " + enabled);
    logger.debug("AUTHORITY AFTER CHANGE: " + authority);
    session.close();
    ManagedSessionContext.unbind(HibernateUtil.createSessionFactory());
    }

}

3 个答案:

答案 0 :(得分:1)

session.flush();
session.getTransaction().commit();
session.close();

尝试删除session.flush();或在session.getTransaction().commit();可能有效后将其删除。

答案 1 :(得分:1)

我认为你不应该以这种方式调用openSession。我强烈建议你重写方法,不要做任何“会话”相关的工作。让Spring处理它,特别是因为你已经在使用@Transactional

无论哪种方式,在lockoutUser()方法中,您找到的用户都不会绑定到之后创建的会话。

ArrayList<UserBean> userAccountValues = getUserAccountDetails(userId); session = HibernateUtil.createSessionFactory().openSession();

因此,稍后在更新该ArrrayList的用户实例的方法中,会话没有意识到要保留用户实例,因为会话从不跟踪它们。

尝试每个线程只有一个会话。每个方法都有自己的事务,但我们很少遇到在线程中需要多个会话的情况。这似乎不是那种情况。

答案 2 :(得分:-2)

您似乎没有打电话给session.save(Object)session.update(Object)