首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用SpringSecurity让SpringBoot1.x项目更安全

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

SpringSecurity框架有两个概念认证和授权,认证可以访问系统的用户,而授权则是用户可以访问的资源,下面我们来简单讲解下SpringBoot对SpringSecurity安全框架的支持。

本章目标

在SpringBoot项目中使用SpringSecurity安全框架实现用户认证以及授权访问。

构建项目

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

图1

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

图2

用户和角色

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

图3

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

图4

因为我们一个用户存在多个角色,一个角色又可以应用到多个用户上,所以我们采用的关联表的方式进行配置关系,用户角色关联表结构如下图5所示:

图5

下面我们根据用户信息表以及角色信息表创建对应的实体,如下图6、图7所示:

图6

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

图7

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

填充测试数据

我们对用户表、角色表、关联表添加几条对应的数据,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_USER、ROLE_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标签库来判断界面的输出,还有如果修改了用户的权限不会实时生效,而需要我们退出用户后再次登录方可生效。

源码地址

SpringBoot码云地址:https://gitee.com/hengboy/spring-boot-chapter

SpringBoot GitHub地址:https://github.com/hengyuboy/spring-boot-chapter

源码章节:Chapter17

开源信息

安全系列

QueryDSL系列文章

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180802G08YSP00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券