UserDetailsService
前文已经认识了 UserDetails,但是 Spring Securit 是从哪获取的用户呢?以及如何添加用户、修改用户?这就是 UserDetailsService 的职责所在了。
先看一下 UserDetailsService 的定义,它只有一个方法,通过 username 来获取用户,返回值是 UserDetails 类型对象。当找不到对应的用户时,会抛出 UsernameNotFoundException。
我们要做的就是实现 loadUserByUsername() 方法,通过读取数据库等方法获取到用户信息。
先实现一个功能简单的 UserDetailsService,功能类似于前面的 InMemoryUserDetailsManager。在实现 UserDetailsService 之前,还需要先实现 UserDetails。
实现 UserDetails,用于创建 UserDetails 对象。
实现 UserDetailsService,用于保存、获取用户。
配置自定义的 InMemoryUserDetailsService,一个简单但完整的示例就完成了。
UserDetailsManager
很多时候,应用中还需要创建、修改、删除用户的功能,Spring Security 就提供了这样一个接口 UserDetailsManager,通过方法名能很清除地明白各个方法的作用。
实际工作中,大部分情况用户都是保存在数据中的,Spring Security 提供了一个通过数据库实现 UserDetailsManager 的类 JdbcUserDetailsManager。它默认(可以自定义)需要两个表:users 表和 authorities 表,users 表至少有 username、password、enabled 三个列,用来保存用户的信息,authorities 表至少有 username、authority 两个列来保存授权,并与用户关联。在 这里可以查看 Spring Boot 如何连接 MySQL 数据库。
users 表
authorities 表
数据库创建完毕后,添加一个用户,然后在 authorities 表中添加一条与用户对应的 authority 数据。这些准备工作完成后,就可以配置 JdbcUserDetailsManager 了。
这里创建了两个用户,user1 和 user2,在 authorities 表中给 user1 添加了授权,没有给 user2 添加授权。user1 可以正常访问,user2 因为没有授权,返回了401。
至此 JdbcUserDetailsManager 就可以工作了,如果数据库表名或列和 JdbcUserDetailsManager 默认的不一致,对象提供了一些方法来修改默认的 SQL 语句,这样就可以灵活发挥了。