第十七章:使用SpringSecurity让SpringBoot项目更安全

SpringSecurity是专门针对基于Spring项目的安全框架,充分利用了依赖注入和AOP来实现安全管控。在不少大型企业级系统中权限是最核心的部分,一个系统的好与坏全都在于权限管控是否灵活,是否颗粒化。在早期的SpringSecurity版本中咱们须要大量的xml来进行配置,而基于SpringBoot整合SpringSecurity框架相对而言简直是重生了,简单到难以想象的地步。git

SpringSecurity框架有两个概念认证受权,认证能够访问系统的用户,而受权则是用户能够访问的资源,下面咱们来简单讲解下SpringBootSpringSecurity安全框架的支持。spring

本章目标

SpringBoot项目中使用SpringSecurity安全框架实现用户认证以及受权访问。数据库

构建项目

咱们使用IntelliJ IDEA工具建立一个SpringBoot项目,预先加入JPA、Security、Druid、MySQL等依赖,项目结构以下图1所示:缓存


图1


咱们下面先来配置数据库访问的配置,将咱们以前章节(第十三章:SpringBoot实战SpringDataJPA)的application.yml配置文件复制到本章项目resources目录下,以下图2所示:安全


图2


用户和角色

数据库链接配置完成后,咱们开始建立本章须要用到的三张表,用户表、角色表、用户角色关联表,一个用户存在多个角色!用户表结构图下图3所示:app


图3


咱们用户表结构仅有三个字段,这里只是为了演示咱们的安全框架,因此不作太过详细。下面是咱们的角色信息表结构以下图4所示:框架


图4


由于咱们一个用户存在多个角色,一个角色又能够应用到多个用户上,因此咱们采用的关联表的方式进行配置关系,用户角色关联表结构以下图5所示:jsp


图5


下面咱们根据用户信息表以及角色信息表建立对应的实体,以下图六、图7所示:spring-boot


图6


能够看到咱们的UserEntity实现了UserDetails接口,UserDetails是SpringSecurity验证框架内部提供的用户验证接口(咱们下面须要用到UserEntity来完成自定义用户认证功能),咱们须要实现getAuthorities方法内容,将咱们定义的角色列表添加到受权的列表内。工具


图7


能够看到咱们的用户实体内添加了对角色的列表支持,并添加了@ManyToMany的关系注解。咱们查询用户时SpringDataJPA会自动查询处关联表user_roles对应用户的角色列表放置到名叫rolesList集合内。

填充测试数据

咱们对用户表、角色表、关联表添加几条对应的数据,SQL脚本以下图8所示:


图8


初始化的SQL脚本已经添加到本章的resources目录下,本章结束为止会有源码下载地址。

配置JPA访问数据

根据建立的UserEntity实体来建立UserJPA接口并继承JPARepository接口,UserJPA内添加一个根据用户名查询的方法,以下图9所示:


图9


咱们能够看到我在图9的UserJPA接口内添加了一个findByUsername方法,这个方法实际上是SpringDataJPA的一个规则,咱们这样写JPA就会认为咱们要根据username这个字段去查询,并自动使用参数索引为0的值(有关SpringDataJPA方法查询后期会在SpringDataJPA 核心技术内体现)。

自定义SpringSecurity用户认证

咱们上面的配置差很少已经完成,下面咱们实现SpringSecurity内的UserDetailsService接口来完成自定义查询用户的逻辑,以下图10所示:


图10


能够看到上图10内的定义,实现UserDetailsService接口须要完成loanUserByUsername重写,咱们使用UserJPA内的findByUsername方法从数据库中读取用户,并将用户做为方法的返回值。

配置SpringSecurity

自定义用户认证已经编写完成,下面咱们须要配置SpringBoot项目支持SpringSecurity安全框架,具体配置代码以下图11所示:


图11


能够看到咱们上图11配置了全部请求都必须登陆访问,第一句咱们仅用了csrd,在springSecurity4.0后,默认开启了CSRD拦截,若是须要配置请在form表单添加以下图12配置:


图12


咱们这里配置了登陆页面127.0.0.1:8080/login请求地址以及登陆错误页面/login?error不被SpringSecurity拦截。下面咱们来编写登陆的JSP页面,咱们以前构建项目的时候并无添加JSP的依赖,下面咱们修改pom.xml添加JSP依赖,以下图13所示:


图13


咱们修改application.yml配置文件添加JSP的页面配置,以下图14所示:


图14


好了,下面咱们简单的建立一个login.jsp页面,页面里面添加一个简单的表单提交,咱们的表单提交地址这里要注意了,SpringSecurity内部已经给咱们定义好了,在4.0版本以后登陆地址都是/login,固然这个/login并非咱们上面配置的loginPage地址。这个地址若是直接访问是访问不到的。必须采用Post形式访问,login.jsp页面内容以下图15所示:


图15


咱们来配置一个简单的SpringBoot内的MVC控制器跳转,下面咱们添加一个名叫MVCConfig配置类继承WebMvcConfigurerAdapter类,重写addViewControllers()方法添加路径访问,能够经过Get形式的/login访问到咱们的login.jsp,代码以下图16所示:


图16


上面有关SpringSecurity配置都已经完成,接下来咱们添加一个IndexController来测试咱们的SprinySecurity框架是否已经生效,咱们上面已经配置了,若是在不登录的状态下只有/login是能够访问的,因此咱们直接访问/index是不可行的。SpringSecurity会直接给咱们重定向到咱们配置的loginPage,IndexController代码以下图17所示:


图17


运行测试

下面咱们来启动项目,先来访问/index查看界面效果,以下图18所示:


图18


正如咱们所说的,当咱们在没有登陆的状态下访问/index时,会直接被安全框架重定向到登陆页面,那么咱们登陆后,再来访问/index并查看界面输出,以下图19所示:


图19


能够看到界面的效果,咱们已经能够正确的访问到index路径所返回的数据,证实了咱们的安全框架已经生效了。

角色判断

咱们在文章开始的部分已经建立了角色表,咱们下面就要根据角色,在用户登陆成功后显示不一样的内容,在这以前咱们须要添加SpringSecurity为咱们提供的JSTL标签库,咱们能够根据标签库自行判断登陆用户的角色,咱们修改pom.xml配置文件添加以下图20所示依赖:


图20


下面咱们建立main.jsp,在jsp页面引入SpringSecurity标签库,并根据角色判断输出内容,以下图21所示:


图21


咱们在main.jsp判断了是超级管理员、普通用户的角色并根据不一样的角色输出不一样的内容,下面咱们重启项目访问127.0.0.1:8080/main地址查看界面输出内容,以下图22所示:


图22


咱们的界面并无输出任何的内容,这是为何呢?

SpringSecurity不支持中文比对,因此咱们这里不能直接使用角色中文名称做为判断条件,下面咱们修改roles信息表添加一个标识字段,以下图23所示:


图23


下面咱们对应的添加RoleEntity实体内字段,以下图24所示:


图24


还有最重要的一点,咱们的UserEntity内是根据RoleName来添加角色受权的,下面咱们须要改为flag,以下图25所示:


图25


最后咱们修改main.jsp,hasRole改为对应的flag字段值,以下图26所示:


图26


上图的ROLE_USERROLE_ADMIN是咱们在roles表内的对应添加的数据,也是做为受权的flag字段值,下面咱们重启项目,登陆后再来访问127.0.0.1:8080/main页面查看界面输出以下图27所示:


图27


界面为了们输出了两条信息,这个是正确的,由于咱们在user_roles表内为admin用户添加了两条对应的角色。下面咱们修改user_roles表结构,删除对应普通用户的关联,再来访问127.0.0.1:8080/main,界面输出效果以下图28所示:


图28


咱们很奇怪,数据为何没有变化呢?由于SpringSecurity将咱们的用户数据、角色数据都缓存到框架内,下面咱们来重启下项目再次访问后,界面输出内容以下图29所示:


图29


此次界面输出的内容才是正确的。

总结

以上内容就是本章的所有内容,本章主要讲解了SpringBoot项目中如何使用SpringSecurity来做为安全框架,并经过SpringSecurity提供的JSTL标签库来判断界面的输出,还有若是修改了用户的权限不会实时生效,而须要咱们退出用户后再次登陆方可生效。

本章的代码以及SQL都已上传到码云:

SpringBoot配套源码地址:gitee.com/hengboy/spr…

SpringCloud配套源码地址:gitee.com/hengboy/spr…

SpringBoot相关系列文章请访问:目录:SpringBoot学习目录

QueryDSL相关系列文章请访问:QueryDSL通用查询框架学习目录

SpringDataJPA相关系列文章请访问:目录:SpringDataJPA学习目录

SpringBoot相关文章请访问:目录:SpringBoot学习目录,感谢阅读!

欢迎加入QQ技术交流群,共同进步。


QQ技术交流群
相关文章
相关标签/搜索