2009-12-07 32 views
2

我试图将Spring Security与Hibernate集成。我对这两种技术都很陌生,所以我几乎肯定会在这里立即采取太多步骤,但我正处于想要从数据库验证用户身份的地步。我认为这肯定更像是一个Spring Security的问题,但我提到它给了一些上下文。以下是错误消息和代码。任何人都可以发现什么org.hibernate.HibernateException:没有会话当前绑定到执行上下文

org.hibernate.HibernateException: No session currently bound to execution context 
    org.hibernate.context.ManagedSessionContext.currentSession(ManagedSessionContext.java:74) 
    org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:622) 
    com.vicinity.dao.hibernate.GenericHibernateDAO.findByCriteria(GenericHibernateDAO.java:99) 
    com.vicinity.dao.hibernate.HibernateUserDAO.getUserByLogin(HibernateUserDAO.java:35) 
    com.vicinity.service.PersistentUserManager.loadUserByUsername(PersistentUserManager.java:67) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    java.lang.reflect.Method.invoke(Unknown Source) 
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    $Proxy31.loadUserByUsername(Unknown Source) 
    org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:83) 
    org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:125) 
    org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:121) 
    org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49) 
    org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:139) 
    org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49) 
    org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:98) 
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) 
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:106) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) 
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) 
    org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:108) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) 
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:150) 
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) 
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) 

配置的DAO和事务管理的:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="configLocation"> 
     <value>classpath:hibernate.cfg.xml</value> 
    </property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<bean id="hibernateUserDAO" class="com.vicinity.dao.hibernate.HibernateUserDAO"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<bean id="userManagerTarget" class="com.vicinity.service.PersistentUserManager"> 
    <property name="userDAO" ref="hibernateUserDAO" /> 
</bean> 

<bean id="userManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
    <property name="transactionManager"> 
     <ref local="transactionManager" /> 
    </property> 
    <property name="target"> 
     <ref local="userManagerTarget" /> 
    </property> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="loadUserByUsername">PROPAGATION_REQUIRED</prop> 
     </props> 
    </property> 
</bean> 

这里是实现UserDetailsService这就是所谓的用户进行身份验证的类。这使得对DAO一个电话,看行userDAO.getUserByLogin(login);

@Service("userManager") 
@Transactional(propagation = Propagation.REQUIRED, readOnly = true) 
public class PersistentUserManager implements UserManager, UserDetailsService { 

     @Override 
     public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException, DataAccessException { 
      User user = userDAO.getUserByLogin(login); 

      if (null == user) { 
       logger.error("User with login: " + login + " not found in database"); 
       throw new UsernameNotFoundException("user not found in database"); 
      } 

      org.springframework.security.core.userdetails.User springUser; 

      springUser = new org.springframework.security.core.userdetails.User(user.getLogin(), user.getPassword(), true, 
        true, true, true, new ArrayList<GrantedAuthority>()); 

      return springUser; 
     } 
    } 

这里是一个从数据库中读取DAO。请注意,我试图采取“GenericDAO模式”的优势:

@Repository("userDAO") 
public class HibernateUserDAO extends GenericHibernateDAO<User, Long> implements UserDAO { 

    public HibernateUserDAO() { 
     super(User.class); 
    } 

    @Override 
    public void createUser(User user) { 
     super.makePersistent(user); 
    } 

    public User getUserByLogin(String login) { 
     if (null == login) { 
      throw new IllegalArgumentException("You must provide a username if you want to get the user."); 
     } 

     List<User> users = findByCriteria(Restrictions.eq("login", login)); 

     // TODO, might need to check here if there are more than one user with the same username 
     if(users == null || users.size() == 0) { 
      return null; 
     } else { 
      return users.get(0); 
     } 
    } 
} 

这里就是发生错误的类,行Criteria crit = getSessionFactory().getCurrentSession().createCriteria(getPersistentClass());

public abstract class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> { 

    private Class<T> persistentClass; 

    private SessionFactory sessionFactory; 

    @SuppressWarnings("unchecked") 
    protected List<T> findByCriteria(Criterion... criterion) { 
     Criteria crit = getSessionFactory().getCurrentSession().createCriteria(getPersistentClass()); 
     for (Criterion c : criterion) { 
      crit.add(c); 
     } 
     return crit.list(); 
    } 
} 

在我的Hibernate配置我有以下(hibernate.cfg.xml),它可能是相关的:

<property name="current_session_context_class">org.hibernate.context.ManagedSessionContext</property> 

回答

0

你配置了事务管理吗?

org.springframework.orm.hibernate3.HibernateTransactionManager 

org.springframework.transaction.interceptor.TransactionProxyFactoryBean 
+0

不,但我现在编辑了我原来的帖子。同样的错误,但我可以看到至少AOP踢。你可以看一下吗? – chrisjleu

2

尝试使用此属性名称。

<property name="hibernate.current_session_context_class"> 
     org.hibernate.context.ManagedSessionContext</property> 

但是,最好将spring配置为负责会话和事务管理。你可以检查this

+0

好吧我已经去配置事务管理,我也改变了你的建议,但没有成功的财产的名称。 – chrisjleu

0

我认为这个问题是未来由于

springUser = new org.springframework.security.core.userdetails.User(user.getLogin(), user.getPassword(), true, true, true, true, new ArrayList<GrantedAuthority>()); 

Spring使用的DAO模板图案,所以当你getUserByLogin会话被Spring创建,当你走出这种方法的会话closed.So当你再次做user.getLogin()没有会话连接,你会得到错误。

尝试使用OpenSessionInViewFilter ....你可能在谷歌搜索它(因为我也没有用它自己,因此不能在这里展示的代码)

你也可以做一两件事,如果你从DAO本身返回springUser(即在getUserByLogin本身,那么它将使用相同的会话对象,它应该工作)

+0

感谢您的回应,但我认为这个答案是不正确的。首先,你引用的代码行甚至没有被执行。其次,我没有使用Spring的模板模式(最近我发现这在使用Hibernate 3时尤其多余)。第三,我的应用程序对用户的表示与Spring Security不同,据我所知,它目前需要为Spring Security框架提供'org.springframework.security.core.userdetails.User1'。 – chrisjleu

+0

是的你是对的,我以前没有看到你没有使用Spring模板模式。 – Rajat

0

我最近碰到了完全相同的错误,并击败我的头靠在墙上找出问题所在。

在我的情况下,我使用web.xml文件中配置的OpenSessionInViewFilter以及那里的Spring Security配置。

由于Spring Security和OpenSessionInViewFilter都是过滤器,因此它们的应用顺序取决于它们在web.xml文件中的显示顺序。

在我的情况下,我最初有OpenSessionInViewFilter下面的春季安全过滤器。一旦我换了他们的职位(即把OpenSessionInViewFilter放在Spring Security之上),一切都很顺利!

相关问题