2014-03-30 84 views
0

如何以我的spring mvc web应用程序使用我的基础MySQL数据库检查用户和密码验证的方式定义我的自定义UserDetailsService bean?为自定义userdetails服务定义bean

以下是具体情况:

我加入安全的spring petclinic样品了解春季安全的一种方式。我正在使用Java配置,并且已经创建了一个SecurityConfig.java文件,它扩展了WebSecurityConfigurerAdapter。我试图设置JdbcAuthentication,该方式利用内置于petclinic样本中的由ClinicService工具管理的MySQL数据库。因此,我创建了一个CustomUserDetailsService类延伸UserDetailsService,并且其intented到SecurityConfig.javaClinicService.java链接。我创建了一个User类和Role类的usersroles表,分别模拟在MySQL数据库。

我加入以下行business-config.xml定义CustomUserDetailService

<bean class="org.springframework.samples.petclinic.service.CustomUserDetailsService"></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 

为了保持这篇文章的简洁,我已经将相关备份材料加载到文件共享网站。您可以点击以下链接阅读所有源代码和完整的堆栈跟踪:

您可以阅读SecurityConfig.javaby clicking on this link
business-config.xml的代码是at this link
CustomUserDetailService.java的代码是at this link
User实体的代码是at this link
Role实体的代码是at this link
完整的堆栈跟踪可以被读取at this link

所有应用程序的其他代码可以在为Spring PetClinic示例,它可以读取by clicking on this link GitHub的页面上找到。

这里是a link to the code for login.jsp

这里是a link to my revised business-config.xml code

+0

匹配角色名称好像你的java的配置风格的配置不检测XML配置定义的bean。看看http://stackoverflow.com/questions/13254779/how-to-import-java-config-class-into-xml-config-so-that-both-contexts-have-beans并尝试添加'< context:annotation-config />'到xml配置,看看它是否有帮助。 –

+0

我会在business-config.xml中的第一个''下面添加它 –

+0

您应该在SecurityConfig中指定一个接口作为依赖项,并让spring容器自动调用一个实现 - 将CustomUserDetailsS​​ervice更改为UserDetailsS​​ervice。另外,如果您打算使用自定义的UserDetailsS​​ervice执行身份验证和授权(例如,如果用户不存在,则为您的UserDetailsS​​ervice抛出UsernameNotFoundException),则不需要jdbc身份验证。 –

回答

4

总结评论,这里是答案。

错在这里有几件事情:

1)的方式,java的配置,那么内部的XML配置文件,<context:annotation-config/>需要存在于XML文件和Java配置进口混合XML的配置和Java配置在Spring类需要被声明为一个bean。 <context:annotation-config/>将启用声明bean的注释处理,然后处理@Configuration注释。阅读文档更多信息:http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-java-combining

修复在business-config.xml中插入<context:annotation-config/>问题。 <bean class="org.springframework.security.samples.petclinic.config.SecurityConfig"></bean>需要<context:annotation-config/>才能工作,因此需要在同一个bean配置文件中声明它们。

2)您在SpringConfig中自动装配具体类(CustomUserDetailsS​​erivce)而不是接口(UserDetailsS​​ervice)。虽然可以使用Spring来自动调用具体类,但通常最好是自动调用接口(Spring会自动调用CustomUserDetailsS​​erivce实现到@Autowired UserDetailsS​​ervice字段)。 Spring在有线类周围创建代理来启用某些功能(如声明性事务),并且此类代理在自动装配时可以轻松实现接口,但如果尝试自动装配到具体类时可能会失败。有可能实现它 - 更多信息在这里:Spring Autowiring class vs. interface? 在这种情况下,自动装入UserDetailsS​​ervice接口肯定会更好,因为这是我们的安全配置实际依赖的。

要解决此问题,指定字段类型的UserDetailsS​​ervice在SpringConfig:

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

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

下面是通过Java配置使用自定义的UserDetailsS​​ervice(弹簧其它地方执行和自动装配)工作弹簧安全配置的例子:

@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()

EDIT 1 - 加入登录表单配置,并链接到文档

EDIT 2 - 加入更多的解释针对问题1)

编辑3 - 更改角色名称表“ADMIN”到“ROLE_ADMIN”中的UserDetailsS​​ervice

+0

向答案添加了附加解释和代码示例。 –

+0

登录表单看起来不错。要调试,我会在loadUserByUsername中设置调试器断点,并查看它是否在登录尝试时执行,并验证您返回的UserDetails是否包含您期望的值。此外,我们允许访问所有人的登录处理URL(请参阅编辑答案的addtional antMatcher。 –

+0

@CodeMed如果你摆脱了这个异常,并且你的UserDetailService被正确注入,你的问题就会得到解答。其余的都是奖金。我认为推动某人解决所有可能的问题直到你能接受他的答案是公平的。如果您在打印文本时遇到问题,请执行一些实际调试并在关键位置设置断点并查看环境。 – Bart