通过ch04,我们已经知道Spring Security是通过UserDetailsService获取用户信息的,ch04中我们建立了基于内存的用户信息获取服务,并预先定义了一个用户。那么在实际生产中,不可能采用这种方式,一般都是通过数据库获取用户信息。那么我们就可以借助扩展UserDetailsService实现。
1.内存用户信息获取方式的流程
该图为Spring Security3.0的说明,4.0后InMemoryDaoImpl已经替换为InMemoryUserDetailsMananger
通过该图我们可以知道,获取用户信息的需求是由DaoAuthenticationProvider要求的,该类包含类型为UserDetailsService成员变量,该变量就是用户信息获取服务,也是我们需要替换的部分。
Spring Security提供了基于Jdbc的用户信息获取服务JdbcUserDetailsManager,该类实现了UserDetailsManager接口,后者继承了UserDetailsService接口,增加了create、update、delete等方法,此外该类还包括DataSource属性,实现了用户信息与具体的数据库的解耦。
Spring Security默认提供了基于HSQLDB内存数据库的建表脚本,如果切换成其他数据库需要修改脚本。默认脚本位于classpath:org/springframework/security/core/userdetails/jdbc/users.ddl,下面给出MySql的脚本
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for authorities
-- ----------------------------
DROP TABLE IF EXISTS `authorities`;
CREATE TABLE `authorities` (
`username` varchar(50) NOT NULL,
`authority` varchar(50) NOT NULL,
UNIQUE KEY `ix_auth_username` (`username`,`authority`),
CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of authorities
-- ----------------------------
INSERT INTO `authorities` VALUES ('admin', 'ROLE_ADMIN');
INSERT INTO `authorities` VALUES ('admin', 'ROLE_USER');
INSERT INTO `authorities` VALUES ('user', 'ROLE_USER');
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`username` varchar(50) NOT NULL,
`password` varchar(500) NOT NULL,
`enabled` tinyint(1) NOT NULL,
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('admin', 'password', '1');
INSERT INTO `users` VALUES ('user', 'password', '1');
SET FOREIGN_KEY_CHECKS=1;
该脚本创建了user表并插入了两条数据。
数据库准备好了,只需要增加一项配置即可将内存用户信息服务替换为数据库服务。修改WebSecurityConfigurerAdapter,增加数据库获取用户信息服务配置。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource);
}
其中dataSource为我们配置的MySql的数据源。
启动服务器,可以测试user和admin连个用户的登录、注销与Remember Me.
代码示例https://github.com/wexgundam/spring.security/tree/master/ch05