我的登录课有问题。如果用户尝试使用用户名登录失败,则应禁用该用户帐户。在运行时,没有错误,但我的数据库没有任何变化。我通过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());
}
}
答案 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)
。