我对SpringSecurity感到困惑。有很多方法可以实现一个简单的事情,我把它们混合在一起。
我的代码如下,但它会抛出异常。如果我删除UserDetailsService
相关代码,则应用程序会运行,我可以登录in-memory
个用户。如下所述,我将配置转换为基于XML,但用户无法登录。
org.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'securityConfig': Injection of autowired dependencies failed; nested
exception is org.springframework.beans.factory.BeanCreationException: Could
not autowire field:
org.springframework.security.core.userdetails.UserDetailsService
com.myproj.config.SecurityConfig.userDetailsService; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying
bean of type
[org.springframework.security.core.userdetails.UserDetailsService] 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),
@org.springframework.beans.factory.annotation.Qualifier(value=userDetailsService)}
Caused by: org.springframework.beans.factory.BeanCreationException: Could not
autowire field
org.springframework.security.core.userdetails.UserDetailsService
com.myproj.config.SecurityConfig.userDetailsService; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type
[org.springframework.security.core.userdetails.UserDetailsService]
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),
@org.springframework.beans.factory.annotation.Qualifier(value=userDetailsService)}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type
[org.springframework.security.core.userdetails.UserDetailsService] 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),
@org.springframework.beans.factory.annotation.Qualifier(value=userDetailsService)}
Web.xml中
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd"
version="3.0">
<listener>
<listener-class>org.apache.tiles.extras.complete.CompleteAutoloadTilesListener</listener-class>
</listener>
<servlet>
<servlet-name>proj</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>proj</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
MvcWebApplicationInitializer
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MvcWebApplicationInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
SecurityWebApplicationInitializer
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
SecurityConfig
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(
passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/resources/**", "/", "/index", "/aboutus")
.permitAll()
.antMatchers("/profile/**")
.hasRole("USER")
.and()
.formLogin().loginPage("/signin").failureUrl("/signin?error")
.permitAll().and().logout().logoutUrl("/signout").permitAll();
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
}
MemberServiceImpl
@Service("userDetailsService")
public class MemberServiceImpl implements UserDetailsService {
@Autowired
MemberRepository memberRepository;
private List<GrantedAuthority> buildUserAuthority(String role) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
setAuths.add(new SimpleGrantedAuthority(role));
List<GrantedAuthority> result = new ArrayList<GrantedAuthority>(
setAuths);
return result;
}
private User buildUserForAuthentication(Member member,
List<GrantedAuthority> authorities) {
return new User(member.getEmail(), member.getPassword(),
member.isEnabled(), true, true, true, authorities);
}
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
Member member = memberRepository.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority("Role");
return buildUserForAuthentication(member, authorities);
}
}
更新1
即使添加了以下注释,SecurityConfig中的authenticationManagerBean
方法也会抛出相同的异常。
@EnableGlobalMethodSecurity(prePostEnabled = true)
更新2
正如其中一个答案中所建议的,我将其转换为基于XML的配置,当前代码如下;但是,当我提交登录表单时,它没有做任何事情。
弹簧security.xml文件
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<beans:import resource='login-service.xml' />
<http auto-config="true" access-denied-page="/notFound.jsp"
use-expressions="true">
<intercept-url pattern="/" access="permitAll" />
<form-login login-page="/signin" authentication-failure-url="/signin?error=1"
default-target-url="/index" />
<remember-me />
<logout logout-success-url="/index.jsp" />
</http>
<authentication-manager>
<authentication-provider>
<!-- <user-service> <user name="admin" password="secret" authorities="ROLE_ADMIN"/>
<user name="user" password="secret" authorities="ROLE_USER"/> </user-service> -->
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="
select username,password,enabled
from Member where username=?"
authorities-by-username-query="
select username
from Member where username = ?" />
</authentication-provider>
</authentication-manager>
</beans:beans>
登录-service.xml中
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/testProject" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
</beans>
答案 0 :(得分:19)
我想你忘了在SecurityConfig Class
上添加这个注释@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(
passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/resources/**", "/", "/index", "/aboutus")
.permitAll().antMatchers("/profile/**").hasRole("USER").and()
.formLogin().loginPage("/signin").failureUrl("/signin?error")
.permitAll().and().logout().logoutUrl("/signout").permitAll();
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
还有一件事我觉得这个bean不需要
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
请尝试这个希望这对你有用..
获取当前用户
public String getUsername() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
if (authentication == null)
return null;
Object principal = authentication.getPrincipal();
if (principal instanceof UserDetails) {
return ((UserDetails) principal).getUsername();
} else {
return principal.toString();
}
}
public User getCurrentUser() {
if (overridenCurrentUser != null) {
return overridenCurrentUser;
}
User user = userRepository.findByUsername(getUsername());
if (user == null)
return user;
}
由于
答案 1 :(得分:15)
我认为问题可能是由于缺少@ComponentScan
注释。尝试在userDetailsService
中自动装配SecurityConfig
时,它无法找到适合自动装配的bean。
Spring应用程序通常还有一个单独的应用程序上下文&#34;,除了&#34; mvc context&#34;,&#34;安全上下文&#34; (你已经通过SecurityConfig
)等等。
我不确定将@ComponentScan
放在SecurityConfig
本身上是否会起作用,但你可以尝试一下:
@Configuration
@ComponentScan("your_base_package_name_here")
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}
替换&#34; your_base_package_name_here&#34;使用包含@Component
或@Service
类的包的名称。
如果这不起作用,请添加一个带有@ComponentScan
注释的新空类:
@Configuration
@ComponentScan("your_base_package_name_here")
public class AppConfig {
// Blank
}
来源:http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch06s02.html
答案 2 :(得分:6)
请参阅代码库中存在的一些错误,请尝试通过查看以下代码来解决此问题。
删除SecurityConfig文件并转换为基于xml文件的配置。
你的spring-security.xml应该是这样的。
<security:http auto-config="true" >
<security:intercept-url pattern="/index*" access="ROLE_USER" />
<security:form-login login-page="/login" default-target-url="/index"
authentication-failure-url="/fail2login" />
<security:logout logout-success-url="/logout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<!-- <security:user-service>
<security:user name="samplename" password="sweety" authorities="ROLE_USER" />
</security:user-service> -->
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username, password, active from users where username=?"
authorities-by-username-query="select us.username, ur.authority from users us, user_roles ur
where us.user_id = ur.user_id and us.username =? "
/>
</security:authentication-provider>
</security:authentication-manager>
web.xml应如下所示:
<servlet>
<servlet-name>sdnext</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sdnext</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/sdnext-*.xml,
</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
<!-- Spring Security -->
<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>
</filter-mapping>
答案 3 :(得分:3)
尝试将以下方法添加到SecurityConfig:
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
答案 4 :(得分:2)
Spring找不到带限定符userDetailsService
的bean。
如果您忘记为Spring Security配置applicationContext.xml
bean,我认为您应该检查UserDetailsService
文件。如果有,请尝试删除@Qualifier("userDetailsService")
。< / p>
点击此链接。 {{3}}
答案 5 :(得分:2)
它表示您的“userDetailsService”bean被声明为 @Autowired ,但它在 SecurityConfig <的上下文中不能作为类( MemberServiceImpl )使用/ em>的
我想在你的 MvcWebApplicationInitializer 中你应该包括 MemberServiceImpl ,如:
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class, MemberServiceImpl.class };
}
答案 6 :(得分:1)
尝试更改字段类型:
declare @test table (QuestionKey nvarchar(100), ResponseValue nvarchar(100))
insert into @test (QuestionKey, ResponseValue)
values
('Cust_3_3_a', ''), ('Cust_3_4_', '-'),
('Cust_3_3_b', ''),
('Cust_3_3_c', ''),
('Cust_3_3_e', 'a'),
('Cust_3_3_f', ''),
('Cust_3_3_g', ''),
('Cust_3_3_h', '')
select * from @test
order by 1 asc
select *,case when QuestionKey IN ('Cust_3_3_a','Cust_3_3_b','Cust_3_3_c') THEN 1
when QuestionKey = 'Cust_3_3_e' THEN 0
when QuestionKey IN ('Cust_3_3_f','Cust_3_3_g','Cust_3_3_h') THEN 1
when QuestionKey = 'Cust_3_4_' AND ResponseValue = '-' THEN 1
when QuestionKey = 'Cust_3_4_' AND ResponseValue <> '-' THEN 0
end test1
from @test
答案 7 :(得分:1)
以下是答案,使用正确的@ComponentScan将解决,下面是我粘贴的示例代码片段,我也面临同样的问题并解决了。以下内容已解决并适用于 org.springframework.security.core.userdetails.UserDetailsService
的bean创建异常相关问题第1步:编写安全应用程序配置类
import org.springframework.security.core.userdetails.UserDetailsService;
@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsServiceImpl")
UserDetailsService userDetailsService;
此处@ComponentScan在 LoginSecurityConfig 中不是必需的,您可以在根配置类中定义@ComponentScan,如下所示,并导入 LoginSecurityConfig.class LoginSecurityConfig。
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.example" })
@Import(value = { LoginSecurityConfig.class })
public class LoginApplicationConfig
第2步:现在自动装配SpringBean org.springframework.security.core.userdetails.UserDetailsService
@Service("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements org.springframework.security.core.userdetails.UserDetailsService {
@Autowired
UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDao.findByUsername(username);
if (user == null) {
System.out.println("User not found");
throw new UsernameNotFoundException("Username not found");
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), true, true, true, true, getGrantedAuthorities(user));
}
private List<GrantedAuthority> getGrantedAuthorities(User user) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return authorities;
}
}//End of Class