Spring Security极简入门三部曲(下篇) - 白泽来了
唐某 2021-05-07 17:54:03 2021-05-07 152 0
目录
Spring Security极简入门三部曲(下篇)
前情回顾
我们已经实现的功能:
- 网站分为首页、登陆页、用户页、管理员页、报错页
- 使用用户名密码登陆,登陆失败报错
- 首页、登陆页所有角色都能访问
- 用户页需要USER或ADMIN权限,管理员页需要ADMIN权限(权限不足时跳转至403页面)
- 如果用户没有登录,则访问需要权限的页面时自动跳转登录页面,登陆成功后自动跳转至访问的页面
- 自定义验证器,当黑客使用baize用户和任意密码登陆后,将获取全部权限
本次添加的功能:
从这篇博客开始,我们将在demo2中加入数据库得到demo3,在保留demo2的功能的基础上,增加两个用户,user2,拥有USER权限,admin2,拥有USER、ADMIN权限,这些数据都将存入数据库中,github项目地址
数据库设计
回顾一下之前给出的数据库模型
当然,本节并不会用到所有的表,规定只在用户<->角色之间进行权限的约束,也就是上图的用户表、角色表、用户角色关系表,建表语句如下:
create table `user`( `user_id` int(11) not null auto_increment, `username` varchar(255) default null comment '姓名', `password` varchar(255) default null comment '密码', primary key (`id`))engine=innodb, charset=utf8;create table `role`( `role_id` int(11) not null auto_increment, `role_name` varchar(255) default null comment '角色', primary key (`id`))engine=innodb, charset=utf8;create table `user_role`( `user_id` int(11) not null, `role_id` int(11) not null, primary key(`user_id`, `role_id`))engine=innodb, charset=utf8;//这个密码是用了工具类对123进行加密后的结果insert into `user`(`user_id`, `username`, `password`)values(1, 'admin2', '$2a$10$h6rzOMVI5lismIclafb7duoVCgN2ShCVr4Nn2Jx772.buyaq7rZKq'),(2, 'user2', '$2a$10$h6rzOMVI5lismIclafb7duoVCgN2ShCVr4Nn2Jx772.buyaq7rZKq');insert into `role`(`role_id`, `role_name`)values(1, 'ROLE_USER'),(2, 'ROLE_ADMIN');insert into `user_role`(`user_id`, `role_id`)values(1, 1),(1, 2),(2, 1);
demo时刻
实现功能:github项目地址
- 从数据库中读取用户名、密码,与前端输l入的信息进行对比验证(user2和admin2,密码为123)
- 验证通过后,登陆用户会得到数据库中存储的角色信息
demo3相比前两个demo增加了较多的文件:
- application.yml中添加了数据库相关的一些配置文件
- 因使用mybatis框架而添加了相关mapper,以及配合使用的实体类,service,xml文件等
- 添加了一个UserDetailsService接口的实现类MyUserDetailsService为核心类
代码分析
MyUserDetailsService是核心,它的主要作用就是自定义了一个数据库验证器加入过滤器链,用于验证前端输入的用户名是否能在数据库中表中查到,并且在查得用户时去查询角色表,为用户赋予角色权限(spring security会为我们做密码错误时的验证,不用人为去处理)
我们只需要在自定义的loadUserByUsername()方法中将参数s当作前端输入的username去使用,并且最后返回一个UserDetails接口的实现类即可(该实现类记录着用户名、密码、权限列表)
```
/**UserDetailsService的实现类,用于在程序中引入一个自定义的AuthenticationProvider,实现数据库访问模式的验证
/
@Servicepublic class MyUserDetailsService implements UserDetailsService {@Autowired
private UserService userService;@Autowired
private RoleService roleService;@Autowired
private UserRoleService userRoleService;@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {Collection<GrantedAuthority> authorities = new ArrayList<>(); //从数据库中取出用户信息 User user = userService.findByName(s); //判断用户是否存在 if (user == null) { throw new UsernameNotFoundException("数据库中无此用户!"