我遇到了Spring autowire的问题。我正在尝试使用Autowire来注入存储库,当我将它注入控制器时,它已经可用于身份验证服务。为了进一步参考,我正在添加相关代码和错误。
的web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Restful Web Application</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
enterprise.util.SpringSecurityConfig
</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>restEnterprise</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restEnterprise</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
restEnterpise-servlet.xml - EmployeeRepository位于dbService
中<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="enterprise.service" />
<context:component-scan base-package="enterprise.controller" />
<context:component-scan base-package="enterprise.util" />
<context:component-scan base-package="dbService" />
<mvc:annotation-driven />
</beans>
SpringSecurityConfig.java
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
private final TokenAuthenticationService tokenAuthenticationService; //handles adding auth token to response and checking for auth header in requests
private final EmployeeDetailsService employeeDetailsService;
public SpringSecurityConfig() {
super(true);
tokenAuthenticationService = new TokenAuthenticationService("tooManySecrets");
employeeDetailsService = new EmployeeDetailsService();
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.debug(true);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.headers().cacheControl().and().and()
.authorizeRequests()
// Allow anonymous logins
.antMatchers("/auth/**").permitAll()
// All other request need to be authenticated
.anyRequest().authenticated().and()
// Custom Token based authentication based on the header previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
}
//http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
@Override
public EmployeeDetailsService userDetailsService() {
return employeeDetailsService;
}
//--------------
@Bean
public TokenAuthenticationService tokenAuthenticationService() {
return tokenAuthenticationService;
}
}
EmployeeDetailsService.java
@Component
public class EmployeeDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
@Autowired
private EmployeeRepository employeeRep;
@Override
public final UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Employee employee = employeeRep.findByLogin(username);
if (employee == null) {
throw new UsernameNotFoundException("Employee not found");
}
List<GrantedAuthority> authorities = buildUserAuthority(employee.getRole());
return buildUserForAuthentication(employee, authorities);
}
// Converts Employee to
// org.springframework.security.core.userdetails.User
private User buildUserForAuthentication(Employee user,
List<GrantedAuthority> authorities) {
return new User(user.getLogin(), user.getPassword(),
true, true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(String userRole) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
setAuths.add(new SimpleGrantedAuthority("ROLE_" + userRole.toUpperCase()));
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
}
部署期间出错
2015-08-18 10:15:34,389 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 1) JBAS014613: Operation ("redeploy") failed - address: ([("deployment" => "enterprise.war")]) - failure description: {"JBAS014671: Failed services" => {"jboss.undertow.deployment.default-server.default-host./enterprise" => "org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./enterprise: Failed to start service
Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dbService.dao.EmployeeRepository enterprise.service.EmployeeDetailsService.employeeRep; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [dbService.dao.EmployeeRepository] 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)}
正如我所说 - 当我在控制器中使用它而不在EmployeeDetailsService中时,这个autowire可以工作。
答案 0 :(得分:1)
不要使用new实例化EmployeeService,而应该让spring容器进行实例化和布线。
您可以将您的员工服务自动装配为
@AutoWired
private final EmployeeDetailsService employeeDetailsService;
并从构造函数中删除新的Instantiation,并从@Bean
方法
userDetailsService()
注释
<强>已更新强>
如果你有一个主弹簧上下文xml将它导入配置类,如下所示
@Configuration
@ImportResource("restEnterpise-servlet.xml")
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter
如果您没有任何弹簧xml,您可以添加组件扫描注释以发现弹簧组件@ComponentScan
答案 1 :(得分:0)
如果您的存储库扩展JpaRepository
,那么您需要在@Resource
@Autowired
代替EmployeeDetailsService
答案 2 :(得分:0)
您的服务在restEnterpise-servlet.xml
中声明,并且您想使用EmployeeRepository
。但是在servlet配置之前加载了安全性配置。因此,您需要创建另一个spring配置,其中将声明所有组件扫描,并将在安全配置之前加载。
例如
spring-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="enterprise.service" />
<context:component-scan base-package="enterprise.controller" />
<context:component-scan base-package="enterprise.util" />
<context:component-scan base-package="dbService" />
<mvc:annotation-driven />
</beans>
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-config.xml
enterprise.util.SpringSecurityConfig
</param-value>
</context-param>
我希望这会对你有所帮助。