我正在尝试使用spring-security进行身份验证,并希望能够在运行时添加用户。我认为使用UserDetailsManager将是最小的侵入性。 如何将其作为bean提供,以便我可以在控制器和其他对象中访问它?
我开始的准则如下:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource, PasswordEncoder enc) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).withDefaultSchema().passwordEncoder(enc)
.withUser("user").password(enc.encode("password")).roles("USER").and()
.withUser("admin").password(enc.encode("password")).roles("USER", "ADMIN");
}
jdbcAuthentication()
创建JdbcUserDetailsManager
,一切正常。但我不知道如何在Web应用程序初始化后访问它。我尝试了两种不起作用的变体:
@Bean
public UserDetailsManager userDetailsManager(DataSource dataSource,PasswordEncoder enc) throws Exception {
return new JdbcUserDetailsManagerConfigurer<>().dataSource(dataSource).withDefaultSchema().passwordEncoder(enc)
.withUser("user").password(enc.encode("password")).roles("USER").and()
.withUser("admin").password(enc.encode("password")).roles("USER", "ADMIN").and()
.getUserDetailsService();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsManager userDetailsManager) throws Exception {
auth.userDetailsService(userDetailsManager);
}
填写登录表单时,我会收到以下信息:
Table "USERS" not found; SQL statement:
select username,password,enabled from users where username = ? [42102-185]
因此,似乎没有正确初始化bean。第二次尝试:
@Bean
public UserDetailsManager userDetailsManager(AuthenticationManagerBuilder auth, DataSource dataSource, PasswordEncoder enc) throws Exception {
return auth.jdbcAuthentication().dataSource(dataSource).withDefaultSchema().passwordEncoder(enc)
.withUser("user").password(enc.encode("password")).roles("USER").and()
.withUser("admin").password(enc.encode("password")).roles("USER", "ADMIN").and()
.getUserDetailsService();
}
在初始化期间,我得到:
java.lang.IllegalStateException: Cannot apply ...JdbcUserDetailsManagerConfigurer@3bd97b0d to already built object
因此,在@Bean
方法中使用构建器也不起作用。
答案 0 :(得分:1)
jdbcAuthentication()
不只是创建JdbcUserDetailsManagerConfigurer
;最重要的是,它使用apply()
注册配置器,以便以后可以按正确的顺序执行所有配置。
幸运的是,apply()
是公开的,所以我们可以自己称呼它。知道了,我们可以使用configurer的备用构造函数将主配置负载移回configureGlobal
。最终对我有用的是:
@Bean
public JdbcUserDetailsManager userDetailsManager(DataSource dataSource) {
JdbcUserDetailsManager mgr = new JdbcUserDetailsManager();
mgr.setDataSource(dataSource); // (1)
return mgr;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, JdbcUserDetailsManager userDetailsManager, DataSource dataSource, PasswordEncoder enc) throws Exception {
//set user detail service manually
auth.userDetailsService(userDetailsManager);
JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> conf =
new JdbcUserDetailsManagerConfigurer<>(userDetailsManager);
//apply the configurer
auth.apply(conf);
conf.dataSource(dataSource) // (2)
.withDefaultSchema().passwordEncoder(enc)
.withUser("user").password(enc.encode("password")).roles("USER").and()
.withUser("admin").password(enc.encode("password")).roles("USER", "ADMIN");
}
似乎在(1)和(2)中设置数据源是多余的,但是在初始化期间留下任何一个都会导致异常:
//without (1)
java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
//without (2)
java.lang.IllegalStateException: DataSource must be set
第一个错误是userDetailsManager()
返回的bean的验证,它是由AuthenticationManagerBuilder执行之前配置器的第二个错误。
像这样配置,我可以写,例如在控制器中:
@Autowired
private UserDetailsManager users;
@Autowired
private PasswordEncoder enc;
@RequestMapping(...)
public String handle(Model model) {
users.createUser(new User(username, enc.encode(password), authorities);
return "view";
}
答案 1 :(得分:0)
如果我说得对,你想创建一个处理用户的bean,我建议在spring.xml中声明它并使用不断添加到bean的函数。 尝试使用applicationcontext,这将在主页上
ApplicationContext ac;
ac=new ClassPathXmlApplicationContext("Spring.xml");
prisontest par=(prisontest)ac.getBean("prison");
这里,applicationcontext就像一个容纳bean的容器,prisontest是定义数据源的类,你可以理解看到spring.xml,
spring.xml将以这种方式显示:
<?xml version="1.0" encoding="UTF-8"?>
<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-2.5.xsd">
<bean id="prison" class="prisontest">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/tgmc" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
</beans>
并且引用数据源的bean将是这样的:
public class prisontest {
DataSource ds;
public void setDataSource(DataSource ds)
{
this.ds=ds;
}
在此处添加代码,以便在运行时管理用户 }
您也可以将其他代码放在同一个类中,希望这会有所帮助。