为自定义userdetailsservice定义bean


问题内容

如何定义自定义UserDetailsServicebean,以使spring mvc
Web应用程序能够使用基础MySQL数据库检查用户和密码的身份验证?

具体细节如下:

我在spring petclinic示例中添加了安全性,作为学习Spring安全性的一种方式。我正在使用Java配置,并设置了一个SecurityConfig.java扩展文件WebSecurityConfigurerAdapter。我试图以JdbcAuthentication一种利用由ClinicServicepetclinic示例中内置的工具管理的MySQL数据库的方式进行设置。因此,我创建了一个CustomUserDetailsService扩展类UserDetailsService,并打算SecurityConfig.java与进行链接ClinicService.java。我创建了一个User类和一个Role类来分别对MySQL数据库中的usersroles表进行建模。

然后,我添加了以下行business-config.xml来定义CustomUserDetailService

<bean class="org.springframework.samples.petclinic.service.CustomUserDetailsService"></bean>

但是,我仍然收到以下错误,指出尚未为其CustomUserDetailService定义bean :

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

为了使发布内容简洁明了,我已将相关备份材料加载到文件共享站点。 您可以通过单击以下链接来阅读所有源代码和完整的堆栈跟踪:

您可以SecurityConfig.java
通过单击此链接进行阅读。
对于该代码business- config.xml在这个环节
对于该代码CustomUserDetailService.java在这个环节。实体
的代码位于此链接上。实体
的代码位于此链接上
完整的堆栈跟踪可以在此链接上读取。
User
Role

该应用程序的所有其他代码都可以在Spring
petclinic示例的github页面上找到,您可以通过单击此链接阅读。

这是login.jsp的代码链接

这是我修改后的business-
config.xml代码的链接


问题答案:

总结评论,这就是答案。

这里有几处错误:

1)在Spring中以将Java配置导入XML配置文件中的方式混合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

要解决此问题,请<context:annotation-config/>在business-
config.xml中插入。<context:annotation-config/>需要<bean class="org.springframework.security.samples.petclinic.config.SecurityConfig"></bean>工作,因此需要在同一bean概要文件中声明它们。

2)您将在SpringConfig中自动装配具体的类(CustomUserDetailsS​​erivce),而不是接口(UserDetailsS​​ervice)。虽然可以使用Spring自动连接具体类,但通常最好将其自动连接到接口(Spring将自动将CreateUserUserDetailsS​​erivce实现连接到@Autowired
UserDetailsS​​ervice字段)。Spring围绕有线类创建代理以启用某些功能(例如声明性事务),并且这些代理在自动装配时可以轻松实现接口,但是如果尝试自动装配到具体类中则可能会失败。尽管有可能实现它-
更多信息,请参见Spring
Autowiring类与接口?

在这种情况下,最好自动连接到UserDetailsS​​ervice接口,因为这实际上是我们的安全配置所依赖的。

要解决此问题,请在SpringConfig中将字段类型指定为UserDetailsS​​ervice:

//Use UseDetailsService interface as field type instead of concrete class CustomUserDao
@Autowired
private UserDetailsService myCustomUserDetailsService;

3)您似乎正在同时设置jdbc身份验证和使用自定义用户详细信息服务的身份验证。如果您希望Spring
Security使用jdbc查询数据库并查找有关现有用户及其角色等信息,通常会使用Spring
JDBC身份验证。如果您想实现对用户/角色等的查询,请使用Custom
UserDetailsS​​erivce。在您的示例中(因为您提供了自定义UserDetailsS​​ervice,它将使用ClinicService查询后端),因此不需要JDBC身份验证。

这是一个使用spring自定义安全性配置的示例,该配置通过java
config使用自定义UserDetailsS​​ervice(在其他地方实现并由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]( http://docs.spring.io/spring-
security/site/docs/3.2.0.RC2/apidocs/org/springframework/security/config/annotation/web/builders/HttpSecurity.html#formLogin())
//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-将角色名称形式从“ ADMIN”更改为“ ROLE_ADMiN”以匹配UserDetailsS​​ervice中的角色名称