Spring Security:(二)设置账号密码三种方式
概述
上一篇文章中,引入 Spring Security 后,项目就被保护起来。但账号只有一个 user,密码也是每次启动项目时生成的。这样不符合实际项目需求,下面介绍其他配置账号密码的方式。Spring Security 有三种配置账号和密码的方式,分别是:
- 通过配置文件
- 通过配置类
- 自定义编写实现类
下面分别说明三种方式。
通过配置文件
在项目的 application.properties 文件中加入下面两行配置
spring.security.user.name=tom
spring.security.user.password=123456
分别对应了账号和密码,重启项目,在访问页面输入上面配置的账号 tom 密码 123456 就可以登录成功。
这种方式可能项目中用的不多,但是 Spring Security 既然设计出来,可能在某些场景下还是用的到的。
通过配置类
如果之前有按照上面通过 配置文件用户 账号密码了,要先清除在配置文件中配置的内容,以免干扰下面内容。如果没有,则继续。
在项目下创建一个 configuration 包,先添加一个配置类 SecurityConfig,里面添加一个 PasswordEncoder 的 Bean,用于密码加密。如果项目中没有这个 Bean 会报错。其代码如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class SecurityConfig { @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
然后在创建一个配置类 MyWebSecurityConfigurerAdapter,并继承 WebSecurityConfigurerAdapter,然后重写父类中一个 configure 方法。其代码如下:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { String password = passwordEncoder.encode("123456"); auth.inMemoryAuthentication().withUser("tom").password(password).roles("admin"); } }
先上一步创建的 PasswordEncoder 的 Bean 注入,在重写的父类方法 configure,此方法的作用是在内存中创建一个名为 tom 的用户,并对密码123456 进行加密。
重启项目后,重新测试登陆。
自定义编写实现类
如果有按照上面 通过配置文件 或 通过配置类 方式配置用户账号密码,要先清除在配置文件中配置的内容和编写的代码,以免干扰下面内容。如果没有,则继续。
第一步 实现 UserDetailService 接口
先在项目中创建一个 Service 包,在里面创建一个 MyUserDetailsService 类,并实现接口 UserDetailsService。其代码如下:
@Service public class MyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1 通过接收到的 username 通过 dao 层从数据库中查数据 Object oject = dao.getMyUserByName(username); // 2 如果没查找则抛出 UsernameNotFoundException 异常 // 3 如果查到了就就将数据库里查到的 object 对象转换成 User 对象 List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("read"); // 这一步是用户权限 User user = new User("tom", "$2a$10$IA0vYLa0B/koVjbo.9s50eeiknFSkS00lqDCnjs9NDTr0ALrIrIOm", auths); return user; } }
重写接口中的 loadUserByUsername 的方法,这里的参数 username 就是用户在页面上填写的用户名,Spring Security 会自动拿到用户名,然后调用这个方法,这个方法返回用户的一些属性,其中就包括密码,这里的密码是在数据库中查的,可以看上面的注释中的伪代码。Spring Security 会将此方法中查询到的正确的用户密码和用户在页面上填写的密码做比对,如果匹配上就登陆成功,否则就失败。密码匹配的过程完全就 Spring Security 内置的方法自动完成。作为开发者要做的就是通过 username 从库里查到正确的密码,告诉 Spring Security 就行。
上面的代码中的 tom 是用户名,也就是 username,后面较长的字符串是密码(密码存入数据库之前都会做加密处理,加密后的密码较长),正常应该是数据库里查询到用户名和用户密码,这里做了简化处理。以某电商项目为例,其中的买家就是一个用户,一个买家包含用户名、密码、地址、性别等信息。但无论这个买家有个多少个属性,一定要有账号和密码,这个一个用户最基本的两个属性。
第二步 配置密码加密的 Bean
在项目下创建一个 configuration 包,先添加一个配置类 SecurityConfig,里面添加一个 PasswordEncoder 的 Bean,后面用于密码加密。其代码如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class SecurityConfig { @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
如果项目中没有配置上面这个 Bean 会报错。
第三步 配置 WebSecurityConfigurerAdapter
然后在创建一个配置类 MyWebSecurityConfigurerAdapter,并继承 WebSecurityConfigurerAdapter,然后重写父类中一个 configure 方法,这里需要用到前两个 Bean。其代码如下:
(其实做了前面两步后,就可以运行项目了,第三步可以省略掉,这里为了便于理解才写了第三步)
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private PasswordEncoder passwordEncoder; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); } }
然后重启项目,输入账号 tom 和密码 123456 就可以登陆成功。
以上就是配置账号密码的三种方式。一般在项目中运用第三种方式,也就是根据用户名 username 从数据库从查到用户的密码 password,然后 Spring Security 自动用数据库查到的密码和前端传过来的密码比对,判断是否登陆成功。