2009-12-07 3 views
2

J'essaie d'intégrer Spring Security avec Hibernate. Je suis novice en ce qui concerne les deux technologies, donc je vais certainement prendre trop de mesures à la fois ici, mais je suis au point où je veux authentifier un utilisateur de la base de données. Je pense que c'est plus un problème de Hibernate qu'un Spring Security, mais je le mentionne pour donner un peu de contexte. Voici le message d'erreur et le code. Quelqu'un peut-il repérer quelque chose?org.hibernate.HibernateException: Aucune session actuellement liée au contexte d'exécution

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) 

Configuration de la gestion de DAO et de transaction:

<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> 

Voici la classe qui implémente l'UserDetailsService qui est appelé à authentifier l'utilisateur. Cela fait un appel à la DAO, voir la ligne 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; 
     } 
    } 

Voici le DAO qui se lit de la base de données. Notez que je suis en train de profiter du « modèle 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); 
     } 
    } 
} 

est ici la classe où l'erreur se produit, la ligne 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(); 
    } 
} 

je suit dans ma configuration de mise en veille prolongée (hibernate.cfg.xml) qui peut être relavent:

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

Répondre

0

Avez-vous configuré la gestion des transactions?

org.springframework.orm.hibernate3.HibernateTransactionManager 

et

org.springframework.transaction.interceptor.TransactionProxyFactoryBean 
+0

Non. Mais j'ai maintenant édité mon article original. Même erreur mais je peux voir l'AOP au moins. Pouvez-vous jeter un coup d'oeil? – chrisjleu

2

Essayez avec ce nom de la propriété. Toutefois, il est préférable que vous configuriez le ressort pour gérer votre session et vos transactions. Vous pouvez vérifier this.

+0

Ok J'ai déjà essayé de configurer la gestion des transactions et j'ai aussi changé le nom de la propriété comme vous l'avez suggéré mais je n'ai pas encore réussi. – chrisjleu

0

Je pense que le problème vient du fait de

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

Spring utilise un motif de modèle dans le DAO, donc quand vous faites getUserByLogin une session est créée au printemps et quand vous sortez de cette méthode, la session est Donc, quand vous faites user.getLogin() encore une fois, il n'y a pas de session jointe et vous obtenez l'erreur.

Essayez d'utiliser OpenSessionInViewFilter .... vous pourriez avoir à effectuer une recherche dans google pour elle (comme je l'ai pas non plus utilisé moi-même, ne peut pas montrer d'où le code ici)

Aussi, vous pouvez faire une chose, si vous renvoyez le springUser du DAO lui-même (c'est-à-dire dans getUserByLogin lui-même, alors il utilisera le même objet de session et cela devrait fonctionner)

+0

Merci pour la réponse, mais je pense que cette réponse est loin d'être la bonne. Premièrement, la ligne de code à laquelle vous faites référence n'est même pas exécutée. Deuxièmement, je n'utilise pas le modèle de modèle de Spring (j'ai lu récemment que cela est devenu largement redondant, surtout en utilisant Hibernate 3). Troisièmement, la représentation de mon application par un utilisateur est différente de celle de Spring Security et pour autant que je sache, il est nécessaire de fournir un 'org.springframework.security.core.userdetails.User1' au framework Spring Security. – chrisjleu

+0

Oui, vous avez raison, je n'ai pas vu plus tôt que vous n'utilisez pas le modèle de modèle de printemps. – Rajat

0

J'ai récemment couru exactement le même genre d'erreur, et battu ma tête contre le mur essayant pour comprendre quel était le problème.

Dans mon cas, j'utilisais le OpenSessionInViewFilter configuré dans le fichier web.xml, ainsi que la configuration Spring Security.

Étant donné que Spring Security et OpenSessionInViewFilter sont des filtres, l'ordre dans lequel ils sont appliqués dépend de l'ordre dans lequel ils apparaissent dans le fichier web.xml.

Dans mon cas, j'avais initialement le OpenSessionInViewFilter sous le filtre de sécurité Spring. Une fois que j'ai échangé leurs positions (c'est-à-dire mettre le OpenSessionInViewFilter au-dessus du Spring Security), tout a bien fonctionné!

Questions connexes