如何定义我的自定义UserDetailsService
bean,使我的spring mvc web app能够使用我的底层MySQL数据库检查用户和密码的身份验证?
以下是具体细节:
我正在为spring petclinic
示例添加安全性,以此作为了解弹簧安全性的一种方式。我正在使用Java配置,并设置了扩展SecurityConfig.java
的{{1}}文件。我试图以一种利用由petclinic样本中内置的WebSecurityConfigurerAdapter
工具管理的MySQL数据库的方式设置JdbcAuthentication
。因此,我创建了一个ClinicService
类,其范围为CustomUserDetailsService
,旨在将UserDetailsService
与SecurityConfig.java
相关联。我创建了一个ClinicService.java
类和一个User
类来分别为MySQL数据库中的Role
和users
表建模。
然后我将以下行添加到roles
以定义business-config.xml
:
CustomUserDetailService
但是我仍然收到以下错误,指出<bean class="org.springframework.samples.petclinic.service.CustomUserDetailsService"></bean>
的bean尚未定义:
CustomUserDetailService
为了简化此帖子,我已将相关备份资料加载到文件共享网站。您可以通过单击以下链接阅读所有源代码和完整堆栈跟踪:
您可以阅读Caused by: java.lang.IllegalArgumentException: Can not set
org.springframework.samples.petclinic.service.CustomUserDetailsService field
org.springframework.security.samples.petclinic.config.SecurityConfig.myCustomUserDetailsService
to $Proxy61
by clicking on this link
SecurityConfig.java
的代码为at this link
business-config.xml
的代码为at this link
CustomUserDetailService.java
实体的代码为at this link
User
实体的代码为at this link
可以读取完整的堆栈跟踪at this link。
应用程序的所有其他代码都可以在Spring petclinic样本的github页面找到,您可以阅读by clicking on this link。
答案 0 :(得分:4)
总结评论,这里是答案。
这里有几个问题:
1)在Spring中混合XML配置和Java配置的方式是在xml配置文件中导入java配置时,<context:annotation-config/>
需要存在于xml文件中,而java配置类需要声明为bean 。 <context:annotation-config/>
将启用声明的bean的注释处理,然后将处理@Configuration注释。请阅读文档:http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-java-combining
修复te-problem插入<context:annotation-config/>
在business-config.xml中。 <context:annotation-config/>
需要<bean class="org.springframework.security.samples.petclinic.config.SecurityConfig"></bean>
才能工作,因此需要在同一个bean配置文件中声明它们。
2)您正在SpringConfig中自动装配一个具体类(CustomUserDetailsSerivce)而不是一个接口(UserDetailsService)。虽然可以使用Spring自动装配具体类,但通常最好自动连接到接口(Spring将自动装配将CustomUserDetailsSerivce实现与@Autowired UserDetailsService字段相结合)。 Spring在有线类周围创建代理以启用某些功能(例如声明式事务),并且此类代理可以在自动装配时轻松实现接口,但如果尝试自动连接到具体类,则可能会失败。虽然有可能实现它 - 更多信息在这里:Spring Autowiring class vs. interface? 在这种情况下,自动连接到UserDetailsService接口肯定会更好,因为这是我们的安全配置实际依赖的。
要解决此问题,请在SpringConfig中将字段类型指定为UserDetailsService:
//Use UseDetailsService interface as field type instead of concrete class CustomUserDao
@Autowired
private UserDetailsService myCustomUserDetailsService;
3)您似乎正在使用自定义用户详细信息服务设置jdbc身份验证和身份验证。如果您希望Spring Security使用jdbc查询数据库并查找现有用户及其角色等,通常会使用Spring JDBC身份验证...如果您希望实现查询用户/角色等自己,则使用自定义UserDetailsSerivce。在您的示例中(因为您提供的自定义UserDetailsService将使用ClinicService查询后端),您不需要JDBC身份验证。
以下是使用自定义UserDetailsService(通过其他地方实现并由spring自动装配)通过java config实现spring安全配置的示例:
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/petclinic/")
.usernameParameter("j_username") // default is username
.passwordParameter("j_password") // default is password
.loginProcessingUrl("/j_spring_security_check") // default is /login with an HTTP post
.failureUrl("/login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/index.jsp")
.and()
.authorizeRequests()
.antMatchers("/**").hasRole("ROLE_ADMIN")
.antMatchers("/j_spring_security_check").permitAll()
.and()
.userDetailsService(userDetailsService);
}
}
我建议阅读实际文档,因为它描述了特定配置构建器方法的作用并提供了示例:http://docs.spring.io/spring-security/site/docs/3.2.0.RC2/apidocs/org/springframework/security/config/annotation/web/builders/HttpSecurity.html#formLogin()
编辑1 - 添加了登录表单配置并链接到文档
编辑2 - 为问题1添加了更多解释
编辑3 - 更改了角色名称表格&#34; ADMIN&#34;到&#34; ROLE_ADMiN&#34;匹配UserDetailsService中的角色名称