Spring Security极简入门三部曲(下篇)

Spring Security极简入门三部曲(下篇)

前情回顾

我们已经实现的功能:

  1. 网站分为首页、登陆页、用户页、管理员页、报错页
  2. 使用用户名密码登陆,登陆失败报错
  3. 首页、登陆页所有角色都能访问
  4. 用户页需要USER或ADMIN权限,管理员页需要ADMIN权限(权限不足时跳转至403页面)
  5. 如果用户没有登录,则访问需要权限的页面时自动跳转登录页面,登陆成功后自动跳转至访问的页面
  6. 自定义验证器,当黑客使用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项目地址

  1. 从数据库中读取用户名、密码,与前端输l入的信息进行对比验证(user2和admin2,密码为123)
  2. 验证通过后,登陆用户会得到数据库中存储的角色信息

demo3相比前两个demo增加了较多的文件:

  1. application.yml中添加了数据库相关的一些配置文件
  2. 因使用mybatis框架而添加了相关mapper,以及配合使用的实体类,service,xml文件等
  3. 添加了一个UserDetailsService接口的实现类MyUserDetailsService为核心类

代码分析

MyUserDetailsService是核心,它的主要作用就是自定义了一个数据库验证器加入过滤器链,用于验证前端输入的用户名是否能在数据库中表中查到,并且在查得用户时去查询角色表,为用户赋予角色权限(spring security会为我们做密码错误时的验证,不用人为去处理)

我们只需要在自定义的loadUserByUsername()方法中将参数s当作前端输入的username去使用,并且最后返回一个UserDetails接口的实现类即可(该实现类记录着用户名、密码、权限列表)

/**
 * UserDetailsService的实现类,用于在程序中引入一个自定义的AuthenticationProvider,实现数据库访问模式的验证
 */
@Service
public 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("数据库中无此用户!");
        }
        //添加权限
        List<UserRole> userRoles = userRoleService.listByUserId(user.getUserId());
        for (UserRole userRole : userRoles) {
            Role role = roleService.findById(userRole.getRoleId());
            authorities.add(new SimpleGrantedAuthority(role.getRoleName()));
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
    }
}

小结

  1. 在demo2的基础上,我们增加了两个用户,我们可以使用这两个用户进行登陆,也可以使用之前定义在内存中的账户进行登陆

  2. 本节的demo3看上去多了很多内容但大多都是mybatis框架的代码和数据库的配置文件,请主要关注MyUserDetailsService实现类,并将其当作定义了一个数据库验证器类,定义了过滤器链中的一个验证规则(类似于一个自定义的AuthenticationProvider实现类)

posted on 2021-05-07 15:06  白泽talk  阅读(425)  评论(1编辑  收藏  举报