【详细】Spring Boot框架整合Spring Security实现安全访问控制

一、 前言:

项目舍弃了原本的SSH框架,改用Spring Boot框架,并且要引入Spring Security为系统提供安全访问控制解决方案,接下来记录一下这两天在Spring Boot中引入Spring Security 的过程。主要参考了以下项目、博客和手册:(目前最新的Spring Security版本为5.0.4,我使用的是5.0.3,前三个链接中用的应该都是Spring Security 4.x或更早版本,想学习最新的Spring Security还是好好读以下第四个链接,Spring Security 5官方文档)

我对Spring Security也还是一知半解,勉强配置好可以使用。可能有一些理解是错误的,或者有一些说法不严谨,请各位见谅和指正。等这段时间忙过去要从头看一下英文版官方手册。

https://github.com/lenve/vhr

https://www.cnkirito.moe/categories/Spring-Security/

https://blog.csdn.net/code__code/article/details/53885510

https://docs.spring.io/spring-security/site/docs/5.0.3.RELEASE/reference/htmlsingle/

-------------------------------------------------------------------------------------------------------------------


二、 Spring Security的原理简介:

Spring Security的安全访问控制分为Authentication(认证)和Authorization(授权,也叫“访问控制”)。认证指的是用户登录的信息验证,判断你账号密码是否正确;授权指的是当用户访问一个页面时判断他有没有这个权限。

一般流程为:

①当用户登录时,前端将用户输入的用户名、密码信息传输到后台,后台用一个类对象将其封装起来,通常使用的是UsernamePasswordAuthenticationToken这个类。

②程序负责验证这个类对象。验证方法是调用Service根据username从数据库中取用户信息到实体类的实例中,比较两者的密码,如果密码正确就成功登陆,同时把包含着用户的用户名、密码、所具有的权限等信息的类对象放到SecurityContextHolder(安全上下文容器,类似Session)中去。

③用户访问一个资源的时候,首先判断是否是受限资源。如果是的话还要判断当前是否未登录,没有的话就跳到登录页面。

④如果用户已经登录,访问一个受限资源的时候,程序要根据url去数据库中取出该资源所对应的所有可以访问的角色,然后拿着当前用户的所有角色一一对比,判断用户是否可以访问。


三、 开发步骤

1. 新建项目

(开发环境IDEA企业版)

新建一个项目,选择Spring Initializr,选择下一步,写好项目的各种信息,选择下一步,选择引入哪些dependency。这里要注意一下,对于一个Spring boot项目来说,最简单的就是选择Web下的Web这个依赖,然后点下一步,确认项目的地址,完成。其他的依赖我们可以在写项目的过程中用到哪个添加哪个,只要在pom.xml文件中添加一个dependency标签就好了。当然,你也可以在创建项目的时候就把要用到的依赖选中,这样项目创建完后pom.xml里面就已经有了这几个dependency的标签了。下面是我选的几个dependency。

创建完,pom.xml文件中的dependency是这样的。


2. 准备工作

在正式写代码之前先做几个准备工作。为了项目的代码分层要分包,再就是把默认的application.properties删掉换成application.yml。


其中,bean是用来存放Entity实体类;component包存放一些Component类,这些类大多被@Component注解,是框架运行过程中需要用到的类;config用来存放一些于Security相关的配置类;controller包存放Controller类,根据前端访问的地址决定如何向前端返回数据;repository包用来存放repository接口,这些接口是用来从数据库中取数据封装成对象的;service存放一些service类,需要依赖Repository接口,实现一些功能逻辑。

3. 建库

MySQL数据库。用户角色与权限管理细分为5个表——用户表、用户-角色表、角色表、角色-权限表、权限表。






以上就是五个表最简单的结构,几条用来测试的简单数据。

至于用户表为什么用users而不用user命名,是因为user在MySQL中是关键字,最好避免使用,所以使用users。不过没关系,在实体类中我们还是用User作为类名的。如今的Spring Boot框架将程序与数据库的耦合度又降低了一个档次,在程序中配置数据库连接和ORM的时候,只有很少地方要注明一下数据库的表名字。

用户的密码是使用BCrypt加密后存储到数据库中的。BCrypt是Spring Security官方推荐的加密方式,在Spring Secueity框架中也提供了这种加密方式,后面会详细介绍。

4. 属性配置文件

接下来写项目的属性配置文件application.yml。


port是服务器的端口,context-path是访问地址前缀,这样我们项目的入口就是http://localhost:8080/mysecurity/。接下来是jdbc的配置,有jdbc经验的一看就懂(不要忘记填密码)。接下来,show-sql为true使得项目进行数据库查询的时候在控制台打印sql语句,方便我们常看和排查错误,ddl-auto有几个属性可选——update、create、create-drop、none、validate,关于它们的区别不懂的话百度一下就明白选哪个了。

如果你是第一次使用yml文件,要注意一个细节,在“:”后面写参数的时候要先打一个空格,这是yml文件格式规定。

5. bean包

在bean包里创建实体类。拿users表来举例。为users表创建实体类的时候,类名、成员变量名字可以不和数据库的表名、列名对应,只要用注解(@Table、@Column)说明一下就好了。另外要在public class User头上加一个@Entity注解。然后添加getter、setter,最好加一个无参构造方法。


如果主键在数据库中是自增主键,那么在实体类中要这么注解一下。这个注解是用来声明自增主键和它的增长策略。


6. repository包

创建完实体类后,要创建repository接口,这就相当于DAO,作用是从数据库取出数据放到对应的实体类中。注意repository是接口类型,且需要继承JpaRepository<T, ID>。前面的T指的是取出数据后封装到哪个类中,后面的ID指的是它的主键类型,下面是我的user的repository接口。


一般情况下这样就可以了,不用声明函数。使用的时候是这个样子的:

@Autowired
private UserRepository userRepository;

public List<User> findAllUsers() {
    List<User> userList = userRepository.findAll();
    return userList;
}

我猜是spring boot帮你把这个接口实现了然后把实例注入到userRepository。所以,虽然你写的是接口,后面却可以使用,而且它还帮你实现了几个方法。

repository接口使用起来很方便,有些方法不需要写,它已经隐示提供了。比如,虽然你的接口里面什么都没写,但已经可以调用userRepository.findAll()方法了。还有一些方法只需要你在接口里面写一行抽象函数声明,不需要有函数体(但是必须按要求给函数命名),就可以在Service里面调用了。

以下这种方式允许你按列名查找数据,同样不需要你写函数体,但是要注意这个抽象函数的命名:findByXxxx(··· ···)。

public interface ResourceRepository extends JpaRepository<Resource, Long> {
    
    public List<Resource> findByUrl(String url);
}

如果你有自己的sql语句,那么你的repository要另外继承一个JpaSpecificationExecutor<T>,T是你的实体类。这样就允许你自己写sql语句。

比如RoleRepository这个接口。这个接口功能比较重要,因为Spring Security框架中某些地方需要根据当前用户查找他对应的所有Role,也有些地方需要根据用户访问的URL查找这个URL对应的所有Role。一种实现方法是在User、Resource的实体类里面添加一个属性:

@OneToMany
@JoinColumn
private List<Role> roles;

使用OneToMany注解,使Repository在从数据库中取users表的记录存放到User实体类中的时候,还会将每条user记录对应的role表中那几条记录一起取出来放到List<Role>中。是一种很方便的方式。如果不使用这种方式,我们也可以在取

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值