org.hibernate.HibernateException: ни один сеанс в настоящее время не связан с контекстом выполнения - PullRequest
2 голосов
/ 07 декабря 2009

Я пытаюсь интегрировать Spring Security с Hibernate. Я новичок в обеих технологиях, поэтому я почти наверняка предпринимаю слишком много шагов одновременно, но сейчас я хочу аутентифицировать пользователя из базы данных. Я думаю, что это, безусловно, больше проблема Hibernate, чем проблема Spring Security, но я упоминаю ее, чтобы дать некоторый контекст. Ниже приведено сообщение об ошибке и код. Кто-нибудь может что-то заметить?

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>

Ответы [ 4 ]

2 голосов
/ 07 декабря 2009

Попробуйте с этим именем свойства.

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

Однако предпочтительно, чтобы вы сконфигурировали Spring так, чтобы он отвечал за ваш сеанс и управление транзакциями. Вы можете проверить это .

0 голосов
/ 23 сентября 2011

Недавно я столкнулся с точно такой же ошибкой и ударился головой о стену, пытаясь выяснить, в чем проблема.

В моем случае я использовал OpenSessionInViewFilter, настроенный в файле web.xml, а также конфигурацию Spring Security.

Поскольку Spring Security и OpenSessionInViewFilter являются фильтрами, порядок их применения зависит от порядка их появления в файле web.xml.

В моем случае у меня изначально был OpenSessionInViewFilter ниже фильтра Spring Security. Как только я поменялся местами (т.е. поставил OpenSessionInViewFilter над Spring Security), все заработало просто отлично!

0 голосов
/ 07 декабря 2009

Я думаю, что проблема наступает из-за

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

Spring использует шаблон Template в DAO, поэтому, когда вы делаете getUserByLogin, Spring создает сеанс, а когда вы выходите из этого метода, сеанс закрывается. Так что, когда вы снова делаете user.getLogin(), сеанс не повторяется прикреплен и вы получите ошибку.

Попробуйте использовать OpenSessionInViewFilter .... вам, возможно, придется поискать его в Google (так как я сам не использовал его, следовательно, не могу показать код здесь)

Также вы можете сделать еще одну вещь, если вы вернете springUser из самого DAO (то есть в самом getUserByLogin, тогда он будет использовать тот же объект сеанса, и он должен работать)

0 голосов
/ 07 декабря 2009

Вы настроили управление транзакциями?

org.springframework.orm.hibernate3.HibernateTransactionManager

и

org.springframework.transaction.interceptor.TransactionProxyFactoryBean
...