通过Spring存储库和服务从数据库中获取,无需会话
我在spring应用程序中使用了一个身份验证过滤器,这要归功于。但是,到目前为止,过滤器只使用一个存储库,该存储库不连接到任何数据库,只返回硬编码的值。我现在正试图从数据库中获取用户详细信息(名称和api密钥) 问题是,每当我从服务类自动连接存储库时,自动连接都会失败。我拥有的存储库依赖于Spring data REST,因为我希望将来还可以从REST API公开用户详细信息:通过Spring存储库和服务从数据库中获取,无需会话,spring,spring-mvc,spring-security,spring-data-jpa,restful-authentication,Spring,Spring Mvc,Spring Security,Spring Data Jpa,Restful Authentication,我在spring应用程序中使用了一个身份验证过滤器,这要归功于。但是,到目前为止,过滤器只使用一个存储库,该存储库不连接到任何数据库,只返回硬编码的值。我现在正试图从数据库中获取用户详细信息(名称和api密钥) 问题是,每当我从服务类自动连接存储库时,自动连接都会失败。我拥有的存储库依赖于Spring data REST,因为我希望将来还可以从REST API公开用户详细信息: @RepositoryRestResource(collectionResourceRel = "users", pa
@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserSecurityRepository extends CrudRepository<Users, Long> {
public Users findByUsername(@Param("uname") String name);
public Users findByApiKey(@Param("key") String apiKey);
}
然后,服务调用存储库(上面粘贴的代码),通过API键从数据库中获取用户:
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
@Service
@Transactional
public class UserSecurityServiceImpl extends UserDetailsService {
@Autowired
private UserSecurityRepository userSecurityRepository;
@Override
public UserDetails loadUserByApiKey(String apiKey) throws UserNotFoundException {
UserDetails userDetails = buildUserDetails(userSecurityRepository.findByApiKey(apiKey));
if (userDetails == null) {
throw new UserNotFoundException("User could not be found with the supplied api key.");
}
return userDetails;
}
但是,由于从服务类自动连接存储库失败,因此此提取失败。我得到这个错误:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userSecurityServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private mypackage.dal.UserSecurityRepository mypackage.services.UserSecurityServiceImpl.userSecurityRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [mypackage.dal.UserSecurityRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
...
我不会使用会话对象访问数据库,因为我希望我的应用程序是无状态的,并且我在security.xml sec:Session management Session-protection=“none”中声明,如您所见:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<sec:http disable-url-rewriting="true" entry-point-ref="forbiddenEntryPoint" use-expressions="true" create-session="never">
<sec:anonymous enabled="false"/>
<sec:session-management session-fixation-protection="none"/>
<sec:custom-filter ref="restAuthenticationFilter" position="FORM_LOGIN_FILTER"/>
<sec:intercept-url pattern="/**" access="isFullyAuthenticated()"/>
</sec:http>
<bean id="forbiddenEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<sec:authentication-manager alias="defaultAuthenticationManager" erase-credentials="true">
<sec:authentication-provider ref="daoAuthenticationProvider"/>
</sec:authentication-manager>
<bean id="daoAuthenticationProvider" class="mypackage.dal.security.RESTDaoAuthenticationProvider">
<property name="userSecurityService" ref="userSecurityServiceImpl"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean>
<bean id="passwordEncoder" class="mypackagedal.security.authentication.HMacShaPasswordEncoder">
<constructor-arg name="strength" value="256"/>
<constructor-arg name="encodeHashAsBase64" value="true"/>
</bean>
<bean id="restAuthenticationFilter" class="mypackage.dal.security.RESTAuthenticationFilter">
<constructor-arg name="defaultFilterProcessesUrl" value="/"/>
<property name="authenticationManager" ref="defaultAuthenticationManager"/>
<property name="authenticationSuccessHandler">
<!-- Upon successful authentication, Spring will attempt to try and move you to another URL -->
<!-- We have to prevent this because the request for the resource and the authentication all get done in the same request! -->
<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<property name="redirectStrategy">
<bean class="mypackage.dal.security.NoRedirectStrategy"/>
</property>
</bean>
</property>
</bean>
</beans>
my@Service访问存储库的方式如下:
@Repository
public class JpaUserSecurityRepositoryImpl {
@PersistenceContext
private EntityManager em;
public Users findByUsername(String name) {
Query query = this.em.createQuery("SELECT users FROM Users WHERE name =:name");
query.setParameter("name", name);
return (Users) query.getSingleResult();
}
public Users findByApiKey(String apiKey) {
Query query = this.em.createQuery("SELECT users FROM Users WHERE api_key =:key");
query.setParameter("key", apiKey);
return (Users) query.getSingleResult();
}
}
@Service
public class UserSecurityServiceImpl implements UserSecurityService {
private UserSecurityRepository repository;
@Autowired
public UserSecurityServiceImpl(UserSecurityRepository repository){
this.repository = repository;
}
我收到以下NoSuchBeanDefinitionException错误:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaUserSecurityRepositoryImpl': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357) ~[spring-orm-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
尝试3:
这次我放弃了不创建会话的愿望,所以我尝试从存储库中使用SessionFactory。我注释掉了security.xml中的一行
<!--<sec:session-management session-fixation-protection="none"/>-->
通过我的服务,我可以访问以下autowired存储库(autowire工作):
@存储库
公共类DataProviderImpl{
@自动连线
私人会话工厂会话工厂;
@交易的
公共列表getUsers(){
Session Session=sessionFactory.openSession();
//我还尝试了:Session Session=sessionFactory.getCurrentSession();
Query Query=session.createQuery(“来自用户u”);
返回query.list();
}
公共用户findByUsername(字符串名称){
List alluser=getUsers();
用于(用户:allusers){
if(user.getFirstName().equals(name)){
返回用户;
}
}
返回null;
}
请注意
Session Session=sessionFactory.openSession();
//我还尝试了:Session Session=sessionFactory.getCurrentSession();
从上面的代码
它编译和部署,但当我打开一个页面时,而不是获取身份验证失败:密钥错误等。我获取身份验证失败:尝试sessionFactory时无法打开连接。openConnection()
当我
身份验证失败:没有绑定到线程的Hibernate会话,并且配置不允许在此创建非事务会话
在存储库中尝试Session Session=sessionFactory.getCurrentSession();时
我真的很想设法从我的数据库中获取这些数据。任何帮助都将不胜感激!非常感谢您的第一次尝试,默认spring context.xml的内容是什么?组件扫描是否包括您的包?我会认为
@RepositoryRestResource
声明on会使这个bean对您可用,但我以前没有使用过spring data REST,所以我不确定。你好,Kevin,非常感谢!也感谢您在github上共享的非常有用的实现;)我的context.xml在我上面文章的“p.S”部分(在尝试2和尝试3之前..我很感激这篇文章可能包含太多的信息,但我希望尽可能详细)。为了让解决这个问题变得简单一点,您可以尝试创建自己的UserSecurityRepository
接口实现。我想知道存储库接口是否会让这里的事情变得混乱,尽管我认为它应该可以工作。请查看FakeUserSecurityRepositoryImpl
类以获取指导。只需插入一个JdbcTemplate并通过它进行实际查询即可。谢谢Kevin,但在attemp2和Attemp3中,我分别使用entitymanager和sessionfactory提供了自己的存储库
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaUserSecurityRepositoryImpl': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357) ~[spring-orm-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
<!--<sec:session-management session-fixation-protection="none"/>-->
@Repository
public class DataProviderImpl {
@Autowired
private SessionFactory sessionFactory;
@Transactional
public List<Users> getUsers() {
Session session = sessionFactory.openSession();
//I also tried: Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("from Users u");
return query.list();
}
public Users findByUsername(String name) {
List<Users> allusers = getUsers();
for (Users user : allusers) {
if (user.getFirstName().equals(name)) {
return user;
}
}
return null;
}